List comprehensions
From Nemerle Homepage
Contents |
Updates
As of r6054 you can use $[1..10] to mean $[x | x in [1..10]]. Also works for $[10,9..1].
As of r6053 we use .. instead of ... in ranges. It is also possible to write [1..10], not only [1 .. 10].
As of r6052 you can use ranges as the collection in foreach. This is expanded to a while loop.
Example
This is implemented as of r6030.
$[ (x, y) | x in l1, x > 3, y in l2, x < y ]
to:
mutable res = []; foreach (x in l1) when (x > 3) foreach (y in l2) when (x < y) res ::= (x, y); res.Rev ()
Generally
$[ expr | cond0, x1 in c1, cond1, ..., xN in cN, condN ]
to:
mutable res = []; when (cond0) foreach (x1 in c1) when (cond1) ... foreach (xN in cN) when (condN) res ::= expr; res.Rev ()
Ranges
Collections can be ranges of the form [x, y .. z], were x, y and z are expressions. This stands for:
def delta = y - x; [x, x + delta, x + 2*delta, ..., x + n*delta]
where x + n*delta <= z (for greatest possible n), or if delta is negative, x + n * delta >= z (for greatest possible n).
There is also a simpler form [x .. y] which is a shorthand for [x, x+1 .. y].
For example:
[1 .. 3] == [1, 2, 3] [1,3 .. 9] == [1, 3, 5, 7, 9] [1,3 .. 10] == [1, 3, 5, 7, 9] [5 .. 1] == [] [5,4 .. 1] == [5, 4, 3, 2, 1]
Expressions x, y and z in [x, y .. z] are executed once for a given range usage, and in the order specified. So the program:
def foo(k) WriteLine ($"foo($k)") k def bar(k) WriteLine ($"bar($k)") k WriteLine ($[ (x,y) | x in [foo (1), foo (3) .. foo (7)], y in [bar (2), bar (4) .. bar (8)] ])
will print:
foo(1) foo(3) foo(7) bar(2) bar(4) bar(8) bar(2) bar(4) bar(8) bar(2) bar(4) bar(8) bar(2) bar(4) bar(8) [(1, 2), (1, 4), (1, 6), (1, 8), (3, 2), (3, 4), (3, 6), (3, 8), (5, 2), (5, 4), (5, 6), (5, 8), (7, 2), (7, 4), (7, 6), (7, 8)]