Credence.Pattern.RedundantListGuard
(credence v0.7.1)
Copy Markdown
Detects is_list/1 guards on a cons-pattern tail variable
([head | tail] when is_list(tail)) that are redundant under the
proper_lists promise.
Why this matters
| The pattern `[head | tail]` destructures a cons cell, but it does not |
guarantee tail is a list: it also matches improper lists like `[1 | 2]`, |
where tail is a non-list. So is_list(tail) is doing real work — it filters
those out. The guard is only redundant when no improper list can reach the
clause, i.e. when the caller promises proper lists.
This rule therefore declares the proper_lists assumption and runs only while
that switch is on (the default). Under :strict it does not fire, because
removing the guard would change behaviour on [1 | 2] (the guarded clause
rejects it and falls through; the unguarded clause matches it).
Flagged patterns
| Pattern | Fix |
|---|---|
def f([h | t]) when is_list(t) | def f([h | t]) |
def f([h | t]) when is_list(t) and is_atom(h) | def f([h | t]) when is_atom(h) |
def f([_ | a], [_ | b]) when is_list(a) and … | Remove each redundant is_list call |
Bad
def max_subarray_sum([first | rest]) when is_list(rest) do
rest
end
def merge([h1 | t1], [h2 | t2]) when is_list(t1) and is_list(t2) do
{t1, t2}
endGood
def max_subarray_sum([first | rest]) do
rest
end
def merge([h1 | t1], [h2 | t2]) do
{t1, t2}
end