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
.