Recursion replaces loops
| No loops in Elixir | |
| Recurse with an accumulator | |
| Tail calls | |
| Reach for Enum first |
No loops in Elixir
Elixir has no while statement that ticks a mutable counter up and down.
Repetition happens when a function calls itself with new arguments, and a base clause stops the chain.
The clause below stops at zero, while the second clause prints and counts down.
defmodule Count do
def down(0), do: :done
def down(n) when n > 0 do
IO.puts(n)
down(n - 1)
end
end
Recurse with an accumulator
An accumulator carries the running result, so each call does a little work and passes the rest forward.
The empty list clause returns the total, and the second clause adds the head and recurses on the tail.
The call below walks three items and answers with their sum.
defmodule Math do
def sum(list), do: total(list, 0)
defp total([], acc), do: acc
defp total([head | tail], acc), do: total(tail, acc + head)
end
Math.sum([1, 2, 3])
Tail calls
A tail call is a recursive call in the last position, with no work left after it returns.
The virtual machine reuses the same frame for such calls, so deep recursion stays lean.
The sketch below keeps the product in acc and finishes the moment it reaches zero.
defmodule Fact do
def of(n), do: go(n, 1)
defp go(0, acc), do: acc
defp go(n, acc), do: go(n - 1, n * acc)
end
Fact.of(5)
Reach for Enum first
Hand written recursion teaches the idea, but daily code uses the Enum module.
Map transforms each item, sum adds them up, and the pipe threads the list through each step.
Reach for these helpers before writing a recursive helper by hand.
[1, 2, 3]
|> Enum.map(&(&1 * 2))
|> Enum.sum()
Next: Lists
Article author: Arthur Isaev