Generally speaking, when mapping over data in Elixir, you want to use the Enum
module. However sometimes you might need to do something more powerful; here you can reach for recursion.
The two most common ways that I use recursion are with lists and binary data (strings). I reach for recursion over Enum.map/2
to process each item of the list in a very specific manner. You can see a complex example here in Kalevala, a text game engine, transforming text into tags.
To write a recursive function, you want at minimum two things: a base case, and the recursive case. The base case is where recursion breaks and a value is returned instead of calling itself again. You can see this in the simple example below.
def sum_orders([]), do: 0
def sum_orders([order | orders]) do
order.total + sum_orders(orders)
end
The sum_orders
function will call recursively until its parameters are an empty List. This is determined by pattern matching, which determines which version of sum_orders
gets called based on the parameters given to it. As long as there is a list of orders in the arguments, the recursive case will be called. It’s a tidier way of saying “If the orders are not empty, keep adding the totals. If they are empty, stop.”
The final thing to be aware of in Elixir’s recursion, is tail call optimization (TCO). When using recursion, as often as you possibly can, make sure the last thing a function calls is itself. TCO lets you avoid a stack overflow, and is how something like a GenServer can run forever by calling the same function over and over.
Header photo by Danny Howe on Unsplash