Enumerables

When we invoke a function in the Enum module, the first argument is usually a collection that must implement a certain protocol.

Enum.map([1, 2, 3], fn(x) -> x * 2 end)
Enum.reduce(1..3, 0, fn(x, acc) -> acc + x end)
Enum.reduce(1..3, 0, &+/2)

Above we see both map and reduce being called.

What does map do?

It returns a list where each item is the result of invoking fun on each respective item of enumerable.

iex> Enum.map([1, 2, 3], fn(x) -> x * 2 end)
[2, 4, 6]

What about reduce?

reduce(enumerable, fun)

It invokes a function for each element in the enumerable, and passes each element and the accumulator as arguments.

The function returns the value stored in the accumulator.

iex> Enum.reduce([1, 2, 3, 4], fn(x, acc) -> x * acc end)
24
iex> Enum.reduce(["I", "Like", "Cheese"], "The truth is:", fn(x, sentence) -> sentence <> " " <> x end)
"The truth is: I Like Cheese"

What other operators are available to Enumerable?

  • all?
  • any?
  • chunk
  • map
  • reduce
  • max
  • sort
  • uniq

We can see all the functions available to Enum with the following command:

Enum.__info__(:functions) |> Enum.each(&(IO.inspect(&1)))

What do we think each of these functions do?

Enum.chunk([1, 2, 3, 4], 2)
Enum.map(1..6, fn(x) -> x - 1 end)
Enum.uniq([1, 1, 1, 2, 3])

Enum.chunk/2 will break up lists into multiple lists based on the integer provided as the second argument.

iex(7)> Enum.chunk([1, 2, 3, 4], 2)
[[1, 2], [3, 4]]

Enum.map/2 will return a new list with each result corresponding to the result of the function.

iex(8)> Enum.map(1..6, fn(x) -> x - 1 end)
[0, 1, 2, 3, 4, 5]

Enum.uniq/1 sill return a list of unique values. (iex(9)> Enum.uniq([1, 1, 1, 2, 3]) [1, 2, 3])