[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

29. "The Iteration Framework"

.setq loop-iteration-framework-section css-number .setq loop-iteration-framework-page page This section describes the way loop constructs iterations. It is necessary if you will be writing your own iteration paths, and may be useful in clarifying what loop does with its input. loop considers the act of stepping to have four possible parts. Each iteration-driving clause has some or all of these four parts, which are executed in this order:

pre-step-endtest
This is an endtest which determines if it is safe to step to the next value of the iteration variable.
steps
Variables which get "stepped". This is internally manipulated as a list of the form (var1 val1 var2 val2 ...); all of those variables are stepped in parallel, meaning that all of the vals are evaluated before any of the vars are set.
post-step-endtest
Sometimes you can't see if you are done until you step to the next value; that is, the endtest is a function of the stepped-to value.
pseudo-steps
Other things which need to be stepped. This is typically used for internal variables which are more conveniently stepped here, or to set up iteration variables which are functions of some internal variable(s) which are actually driving the iteration. This is a list like steps, but the variables in it do not get stepped in parallel.

The above alone is actually insufficient in just about all iteration driving clauses which loop handles. What is missing is that in most cases the stepping and testing for the first time through the loop is different from that of all other times. So, what loop deals with is two four-tuples as above; one for the first iteration, and one for the rest. The first may be thought of as describing code which immediately precedes the loop in the prog, and the second as following the body code--in fact, loop does just this, but severely perturbs it in order to reduce code duplication. Two lists of forms are constructed in parallel: one is the first-iteration endtests and steps, the other the remaining-iterations endtests and steps. These lists have dummy entries in them so that identical expressions will appear in the same position in both. When loop is done parsing all of the clauses, these lists get merged back together such that corresponding identical expressions in both lists are not duplicated unless they are "simple" and it is worth doing. Thus, one may get some duplicated code if one has multiple iterations. Alternatively, loop may decide to use and test a flag variable which indicates whether one iteration has been performed. In general, sequential iterations have less overhead than parallel iterations, both from the inherent overhead of stepping multiple variables in parallel, and from the standpoint of potential code duplication. One other point which must be noted about parallel stepping is that although the user iteration variables are guaranteed to be stepped in parallel, the placement of the endtest for any particular iteration may be either before or after the stepping. A notable case of this is
 
(loop for i from 1 to 3 and dummy = (print 'foo)
      collect i)
  => (1 2 3)
but prints foo four times. Certain other constructs, such as for var on, may or may not do this depending on the particular construction. This problem also means that it may not be safe to examine an iteration variable in the epilogue of the loop form. As a general rule, if an iteration driving clause implicitly supplies an endtest, then one cannot know the state of the iteration variable when the loop terminates. Although one can guess on the basis of whether the iteration variable itself holds the data upon which the endtest is based, that guess may be wrong. Thus,
 
(loop for subl on expr
      ...
      finally (f subl))
is incorrect, but
 
(loop as frob = expr while (g frob)
      ...
      finally (f frob))
is safe because the endtest is explicitly dissociated from the stepping.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Brad Parker on June, 13 2006 using texi2html