List comprehensions are syntactic sugar for looping through enumerables in Elixir. In this chapter we will use comprehensions for iteration and generation.
When we looked at the Enum module in the enumerables chapter, we came across the map function.
Enum.map(1..3, &(&1 * 2))
In this example, we will pass a function as the second argument. Each item in the range will be passed into the function, and then a new list will be returned containing the new values.
Mapping, filtering, and transforming are very common actions in Elixir and so there is a slightly different way of achieving the same result as the previous example −
for n <- 1..3, do: n * 2
When we run the above code, it produces the following result −
[2, 4, 6]
The second example is a comprehension, and as you can probably see, it is simply syntactic sugar for what you can also achieve if you use the Enum.map function. However, there are no real benefits to using a comprehension over a function from the Enum module in terms of performance.
Comprehensions are not limited to lists but can be used with all enumerables.
You can think of filters as a sort of guard for comprehensions. When a filtered value returns false or nil it is excluded from the final list. Let us loop over a range and only worry about even numbers. We will use the is_even function from the Integer module to check if a value is even or not.
import Integer IO.puts(for x <- 1..10, is_even(x), do: x)
When the above code is run, it produces the following result −
[2, 4, 6, 8, 10]
We can also use multiple filters in the same comprehension. Add another filter that you want after the is_even filter separated by a comma.
In the examples above, all the comprehensions returned lists as their result. However, the result of a comprehension can be inserted into different data structures by passing the :into option to the comprehension.
For example, a bitstring generator can be used with the :into option in order to easily remove all spaces in a string −
IO.puts(for <<c <- " hello world ">>, c != ?\s, into: "", do: <<c>>)
When the above code is run, it produces the following result −
helloworld
The above code removes all spaces from the string using c != ?\s filter and then using the :into option, it puts all the returned characters in a string.