<< Prev | - Up - |
The extensions that remain experimental in Mozart 1.1.1 support the use of loops as expressions, i. e. loops that return a value. These extensions are supported by means of additional loop features.
while:E
expression E
is checked on each iteration, just before entering the body of the loop. If it evaluates to false
, we break out of the loop (see break
feature).
until:E
expression E
is checked on each iteration, just after the body of the loop. If it evaluates to true
, we break out of the loop.
Note that it is allowed to use both features in the same loop.
The simplest way for a loop to return a value is to explicitly do so.
return:R
binds R
to a unary procedure. Invoking {R E1}
immediately terminates the loop returning E1
as its value.
default:E2
if the loop terminates without the return procedure having been called, then E2
is returned as the ``default'' value of the loop. Currently E2
is evaluated before starting the loop, but this will hopefully change so that it is only evaluated on exit if necessary. If no default is specified and the return procedure is not invoked, then the loop raises an exception on termination
A loop can be given a hidden accumulator in which a list is incrementally constructed and returned as the value of the loop when the latter terminates. This functionality is obtained by using one or more of the following loop features:
collect:C
binds C
to a unary procedure to accumulate elements of the list. Thus {C E3}
adds E3
as another element of the list. The value will appear in the list in chronological order of collection: the last one collected appears as last element of the list.
append:A
binds A
to a unary procedure to append a list of values to the accumulator.
prepend:P
Similar, but for prepending to the accumulator.
Note that it is possible to use the features above in conjunction with return
. Thus you can accumulate a list, but you can also return a different value e. g. in an exceptional situation.
This functionality is even less official than for the list accumulator: we are not at all convinced that it is sufficiently frequently convenient to warrant special support. It is included simply because it was also in the Common Lisp loop macro which was one source of inspiration.
One way to use an ``hidden'' integer accumulator is for computing the maximum or minimum of a set of values.
maximize:M
binds M
to a unary procedure to accumulate a maximum.
minimum:M
similar but to accumulate a minimum
Note that minimum
and maximum
can both be used in the same loop to update the value of the hidden accumulator. Feature default
can be used to provide a default value in case nothing is accumulated. Feature return
can also be used to return an arbitrary value in exceptional cases.
Another way to use the integer accumulator is for computing the sum of a sequence of values.
sum:S
The initial value of the accumulator is 0. Invoking {S E}
adds E
to the accumulator.
Same idea, but using multiplication
multiply:M
The initial value of the accumulator is 1. Invoking {M E}
multiplies the value of the accumulator by E
.
A loop, using the features described below, is an expression which denotes a list of values that is lazily computed concurrently (i. e. on a separate thread).
yield:E
contributes the value of E
to the stream, then blocks until more of the stream is needed. The yield
feature is very similar to the collect
feature.
yieldAppend
this is to append
like yield
is to collect
.
A generator is a nullary function that returns the next value each time it is invoked, and raises an exception to indicate that all values have been exhausted (any exception will do, as long as it doesn't have label error
or failure
). Correspondingly, the folowing new iterator syntax is introduced:
X from G
where G
is a generator.
<< Prev | - Up - |