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 `[1,2,a,...]`

and X is greater than 3.

The notation `X <- [1,2,a,...]`

is a generator and the expression `X > 3`

is a filter.

An additional filter, `integer(X)`

, can be added to restrict the result to integers:

> [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([Pivot|T]) -> sort([ X || X <- T, X < Pivot]) ++ [Pivot] ++ sort([ X || X <- T, X >= Pivot]); sort([]) -> [].

The expression `[X || X <- T, X < Pivot]`

is the list of all elements in `T`

that are less than `Pivot`

.

`[X || X <- T, X >= Pivot]`

is the list of all elements in `T`

that are greater than or equal to `Pivot`

.

A list sorted as follows:

- The first element in the list is isolated and the list is split into two sublists.
- The first sublist contains all elements that are smaller than the first element in the list.
- The second sublist contains all elements that are greater than, or equal to, the first element in the list.
- Then the sublists are sorted and the results are combined.

The following example generates all permutations of the elements in a list:

perms([]) -> [[]]; perms(L) -> [[H|T] || H <- L, T <- perms(L--[H])].

This takes `H`

from `L`

in all possible ways. The result is the set of all lists `[H|T]`

, where `T`

is the set of all possible permutations of `L`

, with `H`

removed:

> 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 `{A,B,C}`

such that `A**2 + B**2 = C**2`

.

The function `pyth(N)`

generates a list of all integers `{A,B,C}`

such that `A**2 + B**2 = C**2`

and where the sum of the sides is equal to, or less than, `N`

:

pyth(N) -> [ {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:

pyth1(N) -> [{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 `lists.erl`

:

append(L) -> [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:

- All variables that occur in a generator pattern are assumed to be "fresh" variables.
- Any variables that are defined before the list comprehension, and that are used in filters, have the values they had before the list comprehension.
- Variables cannot be exported from a list comprehension.

As an example of these rules, suppose you want to write the function `select`

, which selects certain elements from a list of tuples. Suppose you write `select(X, L) -> [Y || {X, Y} <- L].`

with the intention of extracting all tuples from `L`

, where the first item is `X`

.

Compiling this gives the following diagnostic:

./FileName.erl:Line: Warning: variable 'X' shadowed in generate

This diagnostic warns that the variable `X`

in the pattern is not the same as the variable `X`

that occurs in the function head.

Evaluating `select`

gives the following result:

> 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, `select`

must be written as follows:

select(X, L) -> [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:

f(...) -> Y = ... [ Expression || PatternInvolving Y <- Expr, ...] ...

Instead, write as follows:

f(...) -> Y = ... [ Expression || PatternInvolving Y1 <- Expr, Y == Y1, ...] ...

© 2010–2017 Ericsson AB

Licensed under the Apache License, Version 2.0.