Monday, January 30, 2017

Elixir - Comprehensions

List comprehensions are syntactic sugar for looping through enumerables in Elixir. In this chapter we'll use comprehensions for iteration and generation.

Basics

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're passing 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. We looked at this in functions as first class citizens in Elixir.
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 running the above code, it produces following result:
[2, 4, 6]
The second example is a comprehension, and as you can probably see, it’s simply syntactic sugar for what you could also achieve if you were to 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.

Filter

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’s loop over a range and only worry about even numbers. We’ll 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 running the above code, it produces 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.

:into Option

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 running the above code, it produces 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.

No comments:

Post a Comment