Elixir Comprehensions

Welcome to another tutorial on Elixir. Here you will learn about Comprehensions in Elixir.

In Elixir, list comprehensions are likened to syntactic sugar for looping through enumerables.

 

Basics

In the previous tutorial on Enumerables, in the Enum module, we learned about map functions. Below is an example of the map function.

Enum.map(1..3, &(&1 * 2))

In the above code, we will pass a function as the second argument. Such that each item in the range will be passed into the function, and then a new list will be returned containing the new values.

 

In Elixir, Mapping, filtering, and transforming are very common actions, thus there is a slightly different way of achieving the same result as the example above.

for n <- 1..3, do: n * 2

The output is:

[2, 4, 6]

This example is comprehension, and as you can see, it is simply syntactic sugar for what you can also achieve if you use the Enum.map function. But, there are no real benefits to using a comprehension over a function from the Enum module in terms of performance.

Note that comprehensions are not limited to lists but can be used with all enumerables.

 

Filter

Filters can be regarded as a sort of guard for comprehensions. If a filtered value returns false or nil it is excluded from the final list. Now, let’s loop over a range and only worry about even numbers. The is_even function is used from the Integer module to check if a value is even or not. This is shown below.

import Integer
IO.puts(for x <- 1..10, is_even(x), do: x)

The output is:

[2, 4, 6, 8, 10]

Also, we can use multiple filters in the same comprehension, by simply adding another filter that you want after the is_even filter separated by a comma.

 

:into Option

In above code, all the comprehensions returned lists as their result. But, the result of a comprehension can be inserted into different data structures by simply passing the :into option to the comprehension.

For instance, a bitstring generator can be used with the :into option in order to easily remove all spaces in a string. This is shown below.

IO.puts(for <<c <- " hello world ">>, c != ?s, into: "", do: <<c>>)

The output is:

helloworld

The above code removes all spaces from the string by just using the c != ?s filter and then using the :into option, and it puts all the returned characters in a string.