==================================================================== 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.