Loops

Minilang has several looping constructs:

Loop expressions

The simplest looping expression in Minilang is the loop-expression which repeatedly evaluates a block of code until the loop is exited using an exit-expression somewhere in the body of the loop.

The loop returns the value of the expression after exit, or nil if the expression in omitted.

A next-expression causes the loop to move onto its next iteration immediately.

Normally, exit-expressions are used within conditional expressions such as if-expressions or with and or or. For convenience, Minilang provides while-expressions and until-expressions.

If the first expression after while evaluates to nil then the loop exits with the value of the second expression, or nil is the second expression is omitted. Otherwise, the while-expression evaluates to the result of the first expression.

1while X, Y
2:> behaves like
3if let Temp := X then Temp else exit Y end
4
5while X
6:> behaves like
7if let Temp := X then Temp else exit Temp :<nil>: end

If the first expression after until evaluates to anything other than nil then the loop exits with the value of the second expression, or the value of the first expression if the second expression is omitted. Otherwise, the until-expression evaluates to nil.

1until X, Y
2:> behaves like
3if let Temp := X then exit Y else nil end
4
5until X
6:> behaves like
7if let Temp := X then exit Temp else nil end

Exiting nested loops

The optional expression passed to exit is evaluated in the context of the surrounding loop. For example, to exit 2 loops at once, exit exit Value can be used. Likewise, to skip to the start of the surrounding loop, exit next can be used.

 1let (I, J, K) := for I in 1 .. 10 do
 2   for J in 1 .. 10 do
 3      let K := math::sqrt((I * I) + (J * J))
 4      if K in integer then
 5         exit exit (I, J, K)
 6      end
 7   end
 8end
 9
10print('I = {I}, J = {J}, K = {K}\n')
I = 3, J = 4, K = 5

Named loops

If it is required to exit or restart deeply nested loops, using multiple exit's can be inconvenient and error prone. Minilang allows loops (both loop and for) to be named and then referred to in a exit or next expression.

 1main :- for I in 1 .. 10 do
 2   for J in 1 .. 10 do
 3      if I * J = 9 then
 4         main :- next
 5      end
 6      if (I * I) + (J * J) = (5 * 5) then
 7         main :- exit '{I}^2 + {J}^2 = {5}^2'
 8      end
 9   end
10end
4^2 + 3^2 = 5^2

For expressions

A for-expressions loops over a sequence, binding the generated keys and values to local variables and evaluating a block of code for each iteration. The loop stops when the sequence is exhausted, or if a exit expression is used to exit the loop.

If a for-expression exhausts its sequence without exiting, the else-block will be evaluated and the returned as the value of the for-expression. If the else-block is omitted (usually the case), the value of the for-expression will be nil.

A next-expression can also be used in a for-expression which will advance to the next iteration of the sequence.

1for I in 1 .. 10 do
2   I = 3 and next
3   print('I = {I}\n')
4   I = 8 and exit "Done!"
5end
I = 1
I = 2
I = 4
I = 5
I = 6
I = 7
I = 8
Done!

Each expressions

An each-expression simply loops over a sequence.

1each X
2:> behaves like
3for Temp in X do end