====================================================================
parallel iteration
====================================================================

Sometimes you want to iterate across two lists in parallel, or perhaps
you want to traverse a list while incrementing a variable.

The general syntax of a repeat loop is

 iterator1, iterator2, ..., iteratorN repeat loopbody

where each iterator is either a for or a while clause. The loop 
terminates immediately when the end test of any iterator succeeds or 
when a leave or return expression is evaluated in loopbody. The value
returned by the loop is the unique value of Void.

  l := [1,3,5,7]
   [1,3,5,7]
                      Type: List PositiveInteger

  m := [100,200]
   [100,200]
                      Type: List PositiveInteger

  sum := 0
   0
                      Type: NonNegativeInteger

Here we write a loop to iterate across two lists, computing the sum
of the pairwise product of the elements:

  for x in l for y in m repeat
    sum := sum + x*y
                      Type: Void

The last two elements of l are not used in the calculation because
m has two fewer elements than l.

  sum
   700
                      Type: NonNegativeInteger

This is the "dot product".

Next we write a loop to compute the sum of the products of the loop
elements with their positions in the loop.

  l := [2,3,5,7,11,13,17,19,23,29,31,37]
   [2,3,5,7,11,13,17,19,23,29,31,37]
                      Type: List PositiveInteger

  sum := 0
   0
                      Type: NonNegativeInteger

  for i in 0.. for x in l repeat sum := i * x
                      Type: Void

Here looping stops when the list l is exhaused, even though the
for i in 0.. specifies no terminating condition.

  sum 
   407
                      Type: NonNegativeInteger

When "|" is used to qualify any of the for clauses in a parallel 
iteration, the variables in the predicates can be from an outer
scope or from a for clause in or to the left of the modified clause.

This is correct:
 
  for i in 1..10 repeat
    for j in 200..300 | ood? (i+j) repeat
      output [i,j]

But this is not correct. The variable j has not been defined outside
the inner loop:

  for i in 1..01 | odd? (i+j) repeat -- wrong, j not defined
    for j in 200..300 repeat
      output [i,j]

It is possible to mix several of repeat modifying clauses on a loop:

  for i in 1..10
    for j in 151..160 | odd? j
      while i + j < 160 repeat
        output [i,j]
   [1,151]
   [3,153]
                      Type: Void

Here are useful rules for composing loop expressions:

 1. while predicates can only refer to variables that are global (or
    in an outer scope) or that are defined in for clauses to the left
    of the predicate.
 2. A "such that" predicate (somthing following "|") must directly
    follow a for clause and can only refer to variables that are
    global (or in an outer scope) or defined in the modified for clause
    or any for clause to the left.

