Equals-Then Iteration
If none of the other for
clauses supports exactly the form of variable stepping you need, you can take complete control over stepping with an equals-then clause. This clause is similar to the binding clauses in a **DO**
loop but cast in a more Algolish syntax. The template is as follows:
(loop for var = initial-value-form [ then step-form ] ...)
As usual, var is the name of the variable to be stepped. Its initial value is obtained by evaluating initial-value-form once before the first iteration. In each subsequent iteration, step-form is evaluated, and its value becomes the new value of var. With no then
part to the clause, the initial-value-form is reevaluated on each iteration to provide the new value. Note that this is different from a **DO**
binding clause with no step form.
The step-form can refer to other loop variables, including variables created by other for
clauses later in the loop. For instance:
(loop repeat 5
for x = 0 then y
for y = 1 then (+ x y)
collect y) ==> (1 2 4 8 16)
However, note that each for
clause is evaluated separately in the order it appears. So in the previous loop, on the second iteration x
is set to the value of y
before y
changes (in other words, 1
). But y
is then set to the sum of its old value (still 1
) and the new value of x
. If the order of the for
clauses is reversed, the results change.
(loop repeat 5
for y = 1 then (+ x y)
for x = 0 then y
collect y) ==> (1 1 2 4 8)
Often, however, you’ll want the step forms for multiple variables to be evaluated before any of the variables is given its new value (similar to how **DO**
steps its variables). In that case, you can join multiple for
clauses by replacing all but the first for
with and
. You saw this formulation already in the **LOOP**
version of the Fibonacci computation in Chapter 7. Here’s another variant, based on the two previous examples:
(loop repeat 5
for x = 0 then y
and y = 1 then (+ x y)
collect y) ==> (1 1 2 3 5)