Next: Differences Between Iterate and Loop, Previous: Types and Declarations, Up: Top
Some iterate clauses, or parts of clauses, result in code being moved
from the location of the clause to other parts of the loop. Drivers
behave this way, as do code-placement clauses like initially
and finally. When using these clauses, there is a danger of
writing an expression that makes sense in its apparent location but
will be invalid or have a different meaning in another location. For
example:
(iter (for i from 1 to 10)
(let ((x 3))
(initially (setq x 4))))
While it may appear that the x of (initially (setq x 4))
is the same as the x of (let ((x 3)) ..., in fact
they are not: initially moves its code outside the loop body,
so x would refer to a global variable. Here is another example
of the same problem:
(iter (for i from 1 to 10)
(let ((x 3))
(collect i into x)))
If this code were executed, collect would create a binding for
its x at the top level of the iterate form that the let
will shadow.
Happily, iterate is smart enough to catch these errors; it walks all
problematical code to ensure that free variables are not bound inside
the loop body, and checks all variables it binds for the same problem.
However, some errors cannot be caught:
(iter (with x = 3)
(for el in list)
(setq x 1)
(reducing el by #'+ initial-value x))
reducing moves its initial-value argument to the
initialization part of the loop in order to produce more efficient
code. Since iterate does not perform data-flow analysis, it cannot
determine that x is changed inside the loop; all it can
establish is that x is not bound internally. Hence this code
will not signal an error and will use 3 as the initial value of
the reduction.
The following list summarizes all cases that are subject to these code motion and variable-shadowing problems.
iterate creates a binding, including those used
in with and the into keyword of many clauses.
initially,
after-each, else, finally and
finally-protected.
next or do-next form.
initially arguments of for... initially...
then and for... previous.
then argument of for... initially... then.
initial-value arguments of reducing and
accumulate.
on-failure argument of finding... such-that.