Credence.Rule.NoLengthInGuard (credence v0.2.0)

Copy Markdown

Performance rule: Detects the use of length/1 inside guard clauses (when).

length/1 traverses the entire list to compute its size, making it O(n). When placed in a guard, this cost is paid on every function call attempt, and the list is almost always traversed again inside the function body.

Bad

def process(list) when length(list) > 0 do
  Enum.map(list, &(&1 * 2))
end

def kth_largest(nums, k) when k <= length(nums) do
  Enum.sort(nums, :desc) |> Enum.at(k - 1)
end

Good

def process([_ | _] = list) do
  Enum.map(list, &(&1 * 2))
end

def kth_largest(nums, k) do
  if k > length(nums), do: raise(ArgumentError, "k out of bounds")
  Enum.sort(nums, :desc) |> Enum.at(k - 1)
end

For non-empty checks, pattern matching ([_ | _]) is O(1) and idiomatic. For bounds checks, moving the validation into the function body avoids redundant traversals when the guard fails and another clause is tried.