This section starts with a simple example, showing a generator and a filter:
> [X || X <- [1,2,a,3,4,b,5,6], X > 3]. [a,4,b,5,6]
This is read as follows: The list of X such that X is taken from the list
The notation
An additional filter,
> [X || X <- [1,2,a,3,4,b,5,6], integer(X), X > 3]. [4,5,6]
Generators can be combined. For example, the Cartesian product of two lists can be written as follows:
> [{X, Y} || X <- [1,2,3], Y <- [a,b]]. [{1,a},{1,b},{2,a},{2,b},{3,a},{3,b}]
The well-known quick sort routine can be written as follows:
sort([ X || X <- T, X < Pivot]) ++
[Pivot] ++
sort([ X || X <- T, X >= Pivot]);
sort([]) -> [].]]>
The expression
A list sorted as follows:
The following example generates all permutations of the elements in a list:
[[]];
perms(L) -> [[H|T] || H <- L, T <- perms(L--[H])].]]>
This takes
> perms([b,u,g]). [[b,u,g],[b,g,u],[u,b,g],[u,g,b],[g,b,u],[g,u,b]]
Pythagorean triplets are sets of integers
The function
[ {A,B,C} ||
A <- lists:seq(1,N),
B <- lists:seq(1,N),
C <- lists:seq(1,N),
A+B+C =< N,
A*A+B*B == C*C
].]]>
> pyth(3). []. > pyth(11). []. > pyth(12). [{3,4,5},{4,3,5}] > pyth(50). [{3,4,5}, {4,3,5}, {5,12,13}, {6,8,10}, {8,6,10}, {8,15,17}, {9,12,15}, {12,5,13}, {12,9,15}, {12,16,20}, {15,8,17}, {16,12,20}]
The following code reduces the search space and is more efficient:
[{A,B,C} ||
A <- lists:seq(1,N-2),
B <- lists:seq(A+1,N-1),
C <- lists:seq(B+1,N),
A+B+C =< N,
A*A+B*B == C*C ].]]>
As an example, list comprehensions can be used to simplify some
of the functions in
[X || L1 <- L, X <- L1].
map(Fun, L) -> [Fun(X) || X <- L].
filter(Pred, L) -> [X || X <- L, Pred(X)].]]>
The scope rules for variables that occur in list comprehensions are as follows:
As an example of these rules, suppose you want to write
the function
Compiling this gives the following diagnostic:
./FileName.erl:Line: Warning: variable 'X' shadowed in generate
This diagnostic warns that the variable
Evaluating
> select(b,[{a,1},{b,2},{c,3},{b,7}]). [1,2,3,7]
This is not the wanted result. To achieve the desired
effect,
[Y || {X1, Y} <- L, X == X1].]]>
The generator now contains unbound variables and the test has been moved into the filter.
This now works as expected:
> select(b,[{a,1},{b,2},{c,3},{b,7}]). [2,7]
A consequence of the rules for importing variables into a list comprehensions is that certain pattern matching operations must be moved into the filters and cannot be written directly in the generators.
To illustrate this, do not write as follows:
Y = ...
[ Expression || PatternInvolving Y <- Expr, ...]
...]]>
Instead, write as follows:
Y = ...
[ Expression || PatternInvolving Y1 <- Expr, Y == Y1, ...]
...]]>