Loops

While/Until

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 ).

For

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 C
This binding works on a Collection C. 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 M
This binding works on a Map M. 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 A
The loop variable is bound to successive integers starting from A. This binding has to be combined with another in order for the loop to finish!
id from A to B
The loop variable is bound to successive integers, starting from A and finishing at B

Each condition requires some explanation :-

while E else E2
This condition evaluates expression E 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 E2
This conditon is a synonym for while not E
where E
Any of the Bindings can be followed by a where 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