loops
An expression of the form while X do Y operates by evaluating
     X repeatedly.  Each time the value of X is true, 
     Y is evaluated and its value is discarded.  When finally
     the value of X is false the special value null is 
     returned as the value of the while expression.
  
    | i1 : i = 0; | 
  
    | i2 : while i < 20 do (<< " " << i; i = i + 1); << endl;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 | 
In the example above, X is the predicate i < 20 and Y is
     the code (<< " " << i; i = i + 1).  Notice the use of the
     semicolon within Y which separates two expression.
The semicolon can also be used with the predicate X to do other things
     before the test is performed.  This works because the value of an expression
     of the form (A;B;C;D;E) is obtained by evaluating each of the
     parts, and providing the value of the last part (in this case, E),
     as the value of the whole expression.  Thus, if the value of E is always
     true or false, the expression (A;B;C;D;E) can be used as
     the predicate X.  We illustrate this in the following example.
  
    | i4 : i = 0; | 
  
    | i5 : while (<< " " << i; i < 20) do i = i+1; << endl0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 
 o6 = stdio
 
 o6 : File
 | 
As a further indication of the power of this construction, consider
     an expression of the following form.          while (A; not B) and (C; not D) do (E; F)
It is the Macaulay 2 equivalent of C code that looks like this:          while (TRUE) { A; if (B) break; C; if (D) break; E; F; }




