List Comprehension
Do you remember the lists:map/2
and lists:filter/2
functions from the previous post? If not, consult the Lists & lists Module post. lists:map(Function, List)
returns a new list that results from List
after applying the Function
to each element. lists:filter(Predicate, List)
returns a list that contains only the elements of List
for which the call to Predicate
returns true.
Both the aforementioned operations are commonly used, as well as their combination; map & filter (does it remind you map & reduce?). Erlang provides this combined functionality using the list comprehension construct.
Format
A list comprehension look like the following:
[Expression || Generators1, Guards1, Generators2, ...] |
[Expression || Generators1, Guards1, Generators2, ...]
Generators
As their name suggests, generators create the data used in the filter-map operations. A generator has the Pattern <- Data
format, where Data
is a list or an expression that results to a list and Pattern
is a pattern used to match with the elements of the list. This pattern can be used to disassembly elements. For example, two valid generators are I <- lists:seq(1, 10)
and {X, Y} <- [{'A', 'Excellent'}, {'B', 'Good'}, {'C', 'Fair'}]
.
Expression
The expression specifies the elements of the result. For example, [I || I <- [1, 2, 3]]
returns the input list element as is.
Guards
Guards are expressions that return either true
or false
, the same as the guards we have seen in the previous posts. They apply to the variables that are on the left of the guard and the ones that are accessible due to the scope where the comprehension runs. For example, I <- [1, 2, 3, 4], I rem 2 == 0
is a valid generator - guard combination (the result should be obvious; only the even numbers "pass" the guard's test).
Read the rest of this entry »