Credence.Rule.NoManualListLast
(credence v0.2.0)
Copy Markdown
Detects hand-rolled reimplementations of List.last/1.
Why this matters
When NoListLast flags List.last/1, LLMs "fix" it by writing the
exact same O(n) traversal under a different name:
# Flagged — this IS List.last, just hand-rolled
defp get_last_element([val]), do: val
defp get_last_element([_ | rest]), do: get_last_element(rest)This has the same performance characteristics as List.last/1 but
adds unnecessary code. The real fix is to restructure the algorithm
to avoid needing the last element:
- Track the value in an accumulator during a reduce
- Reverse the list and take the head
- Destructure from the other end
Detection scope
A two-clause defp (or def) function with arity 1 where:
- One clause matches
[val](single-element list) and returnsval The other clause matches
[_ | rest]and recurses withrest
Severity
:warning