Elixir Enum Reduce
Enum.reduce walks a collection one item at a time while carrying a single running value. That running value is called the accumulator, and each step replaces it with a new value built from the current item.
Reduce totals a list step by step
The sum reduce starts its accumulator at 0 and adds each number in turn. The product reduce starts at 1 and multiplies instead.
numbers = [200, 30, 4]
total = Enum.reduce(numbers, 0, fn n, acc -> n + acc end)
IO.puts(total)
product = Enum.reduce(numbers, 1, fn n, acc -> n * acc end)
IO.puts(product)Building at the front reverses the order
Each doubled number goes onto the front of the accumulator list. The finished list therefore runs in reverse order.
numbers = [1000, 2000, 3000]
doubled = Enum.reduce(numbers, [], fn n, acc -> [n * 2 | acc] end)
IO.inspect(doubled)Reduce reverses a list by hand
Adding each word to the front of an empty list flips the whole list. The second line shows the original list is unchanged.
words = ["first", "second", "third"]
reversed = Enum.reduce(words, [], fn word, acc -> [word | acc] end)
IO.inspect(reversed)
IO.inspect(words)Example
prices = [250, 175, 300]
total = Enum.reduce(prices, 0, fn price, acc -> price + acc end)
count = Enum.reduce(prices, 0, fn _price, acc -> acc + 1 end)
IO.puts(total)
IO.puts(count)
IO.inspect(Enum.reduce(prices, [], fn price, acc -> [price * 2 | acc] end))Key points
- Reduce: Enum.reduce takes a collection, a starting value, and a combining function.
- Accumulator: the accumulator is the running value that each step updates.
- Function shape: the combining function receives the item first and the accumulator second.
- Starting value: the starting value is the accumulator before the first item is read.
- Building: a reduce can build a new list by adding each result to the front of the accumulator.
- Order effect: adding items to the front of a list builds that list in reverse order.
In this example, the first reduce adds the prices into a total of 725. The second reduce counts the prices by adding 1 for each one, giving 3. The last reduce doubles each price onto the front of a list, so the results appear in reverse order.
Note
Enum.sum and Enum.count are ready-made shortcuts for two common reduces.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does Enum.reduce([1, 2, 3], 10, fn n, acc -> n + acc end) return?