Credence.Pattern.NoEnumAtNegativeIndex (credence v0.4.5)

Copy Markdown

Detects Enum.at/2 called with a negative integer literal index.

Elixir lists are singly-linked, so Enum.at(list, -1) traverses the entire list to reach the last element. Calling Enum.at(list, -2) does the same to reach the second-to-last, and so on — each call pays O(n).

When multiple negative-index accesses target the same list, the cost multiplies unnecessarily.

Bad

last = Enum.at(sorted_list, -1)
one_before_last = Enum.at(sorted_list, -2)

value = sorted |> Enum.at(-1)

Good

# For multiple tail elements, reverse once and pattern-match
sorted_list_reversed = Enum.reverse(sorted_list)
[last, one_before_last | _] = sorted_list_reversed

# For a single last element, use List.last/1
value = List.last(sorted)

Auto-fix

When multiple assignments access the same list variable with negative indices within the same function, the fixer groups them into a single Enum.reverse/1 call and a pattern match (up to depth 5).

A lone Enum.at(x, -1) is rewritten to List.last(x).

A lone Enum.at(x, -N) where N > 1 is rewritten to a reverse + pattern match on a single variable.