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.