The simplest loops is the while loop. This has the form
shown below. It repeatedly evaluates the body
S while the predicate E
evaluates to true. Note that E must evaluate
to a boolean value. Importantly, the loop returns all the values
generated by the evaluations of S.
while E do S endwhile
until E do S enduntil
The while loop has a trivial variant, the
until loop. As you should expect by now, until
E is simply an alternative for while not(
E ).
However, the real looping power of MillScript is provided by the
for loop. Although describing it is fairly complicated,
using it is easy. The for loop provides a way to
iterate across one or more objects at the same time.
Here's the grammar.
for (Binding|Condition)* do S finally E endfor
Binding ::=
i in C # list iteration
k & v in M # map iteration
id from A # counting (forever)
id from A to B # counting
Condition ::=
while E else E
until E then E
where E # this is slightly different, see notes below
To summarize this, a for loop has several
Bindings, Conditions, a loop body
S and optional finally expression. Each time round the loop, all the bindings
are asked produce their next values. If any binding is exhausted the
loop finishes. If all the bindings produce values the loop variables
are set and the loop body is evaluated. When the loop exits, it
returns all the values generated by the evaluations of
S, then the optional E
will be evaluated.
Each binding requires some explanation :-
i in CC. It binds
i to each element of C
in turn. If C evaluates to a non-Collection,
the Collection conversion is applied. In particular, if
C is bound to a Map then the values of that
map are used as the Collection. [If you are a Java programmer, it
helps to know that Maps are converted to Collections using
java.util.Map.values().]
k & v in MM. It binds
k and v to the key and
value of each maplet of the Map. If M
evaluates to anything other than a Map, Map conversion is applied.
In particular, Lists, Strings and Elements are all automatically
converted. [If you are a Java programmer, it helps to know that a
maplets in question are the Map.Entry values from the
java.util.Map.entrySet(). Also, the List conversion is responsible
for the implementation of 1-indexing.]
id from AA. This binding has to be combined with
another in order for the loop to finish!
id from A to BA and finishing at B
Each condition requires some explanation :-
while E else E2E and
terminates the loop if if evaluates to false. If this condition
causes the loop to terminate, expression E2
will be executed if present, otherwise the standard
finally expression will be executed.
until E then E2while not E
where Ewhere
clause. This works somewhat like a filter, where the binding only
succeeds if the expression E evaluates to
true. If the expression evaluates to false, the current loop
iteration is skipped, e.g.
:-) for x from 1 to 10 where x mod 2 = 0 do endfor;
There are 5 results
2
4
6
8
10