CLAIRE supports two types of loops: iteration and conditional loops (while and until).
Iteration is uniquely performed with the for statement, it can be performed on any collection :
for x in (1 .. 3) a[x] := a[x + 3] for x in list{x in class | size(x.ancestors) >= 4} printf("~S \n", x) |
A collection here is taken in a very general sense, i.e., an object that can be seen as a set
through the enumeration method set!. This includes all CLAIRE types but is not restricted since
this method can be defined on new user classes that inherit from the collection root. For instance,
set!(n:integer) returns the subset of (0 .. 29) that is represented by the integer n taken as
a bit-vector. To tell CLAIRE that her new class is a collection, the user must define it as a
subclass of collection. If x is a collection, then :
are supported. When defining a new subclass of collection, the methods set! and % must be
defined for this new class, and it is also advisable to define size and iterate to get compiler
speed-ups (if size is not defined, an implicit call to set! is made). Other collection handling
methods, such as add, delete, etc may be defined freely if needed. Notice that it is possible that the expression being evaluated inside the loop modifies the
set itself, such as in :
for x in {y in S | P(y)} P(x) := false |
Because the CLAIRE compiler tries to optimize iteration using lazy evaluation, there is no
guarantee about the result of the previous statement. In this case, it is necessary to use an
explicit copy as follows :
for x in copy({y in S | P(y)}) P(x) := false |
The iteration control structure plays a major role in CLAIRE. It is possible to optimize its
behavior by telling CLAIRE how to iterate a new subclass (C) of collection. This is done through
adding a new restriction of the property iterate for this class C, which tells how to apply a given
expression to all members of an instance of C. This may avoid the explicit construction of the
equivalent set which is performed through the set! method. Conditional loops are also standard (the exiting condition is executed before each loop in a while
and after each loop in a until),
while (x > 0) x :+ 1 until (x = 12) x :+ 1 while not(i = size(l)) (l[i] := 1, i :+ 1) |
The value of a loop is false. However, loops can be exited with the break(x) instruction, in which
case the return value is the value of x :
There is one restriction with the use of break: it cannot be used to escape from a try ... catch
block. This situation will provoke an error at compile-time.