Credence.Pattern.NoIdentityEnumMap (credence v0.8.0)

Copy Markdown

Detects Enum.map/2 called with an identity function callback, which is just a verbose Enum.to_list/1.

Enum.map(enum, fn x -> x end) walks the enumerable and rebuilds every element unchanged — the closure does nothing. The idiomatic spelling of "materialise this enumerable into a list" is Enum.to_list/1.

Why Enum.to_list/1 and not just the bare argument

Dropping the call entirely (Enum.map(enum, & &1)enum) is not behaviour-preserving: Enum.map/2 always returns a list, so on a map it returns a keyword list, on a range a list, and on a non-enumerable (a bare string, an integer) it raises Protocol.UndefinedError. Enum.to_list/1 has the identical contract on every one of those inputs, so the rewrite is safe with no assumptions. (A "delete it" rule would need to prove the argument is statically a list — see no_enum_count_for_length for that style.)

Bad

Enum.map(list, fn x -> x end)
list |> Enum.map(& &1)
Enum.map(enum, &Function.identity/1)

Good

Enum.to_list(list)
list |> Enum.to_list()
Enum.to_list(enum)

Auto-fix

Rewrites Enum.map(enum, identity) to Enum.to_list(enum) and the piped form |> Enum.map(identity) to |> Enum.to_list(). Handles fn x -> x end, & &1, &(&1), and &Function.identity/1 as identity functions.