Blocks and Exits
Control Structure
Loop Facility
The macros described here provide more sophisticated, high-level
looping constructs to complement Emacs Lisp's basic while
loop.
loop
and the extremely powerful and flexible feature known as
the Loop Facility or Loop Macro. This more advanced
facility is discussed in the following section; see Loop Facility.
The simple form of loop
is described here.
If loop
is followed by zero or more Lisp expressions,
then (loop exprs...)
simply creates an infinite
loop executing the expressions over and over. The loop is
enclosed in an implicit nil
block. Thus,
(loop (foo) (if (no-more) (return 72)) (bar))
is exactly equivalent to
(block nil (while t (foo) (if (no-more) (return 72)) (bar)))
If any of the expressions are plain symbols, the loop is instead interpreted as a Loop Macro specification as described later. (This is not a restriction in practice, since a plain symbol in the above notation would simply access and throw away the value of a variable.)
(var [init [step]])
The loop works as follows: First, each var is bound to the
associated init value as if by a let
form. Then, in
each iteration of the loop, the end-test is evaluated; if
true, the loop is finished. Otherwise, the body forms are
evaluated, then each var is set to the associated step
expression (as if by a psetq
form) and the next iteration
begins. Once the end-test becomes true, the result
forms are evaluated (with the vars still bound to their
values) to produce the result returned by do
.
The entire do
loop is enclosed in an implicit nil
block, so that you can use (return)
to break out of the
loop at any time.
If there are no result forms, the loop returns nil
.
If a given var has no step form, it is bound to its
init value but not otherwise modified during the do
loop (unless the code explicitly modifies it); this case is just
a shorthand for putting a (let ((var init)) ...)
around the loop. If init is also omitted it defaults to
nil
, and in this case a plain `var
' can be used
in place of `(var)
', again following the analogy with
let
.
This example (from Steele) illustrates a loop which applies the
function f
to successive pairs of values from the lists
foo
and bar
; it is equivalent to the call
(mapcar* 'f foo bar)
. Note that this loop has no body
forms at all, performing all its work as side effects of
the rest of the loop.
(do ((x foo (cdr x)) (y bar (cdr y)) (z nil (cons (f (car x) (car y)) z))) ((or (null x) (null y)) (nreverse z)))
do
what let*
is to let
. In
particular, the initial values are bound as if by let*
rather than let
, and the steps are assigned as if by
setq
rather than psetq
.
Here is another way to write the above loop:
(do* ((xp foo (cdr xp)) (yp bar (cdr yp)) (x (car xp) (car xp)) (y (car yp) (car yp)) z) ((or (null xp) (null yp)) (nreverse z)) (push (f x y) z))
nil
) is evaluated
with var bound to nil
to produce the result returned by
the loop. The loop is surrounded by an implicit nil
block.
result
form is evaluated with var bound to the total
number of iterations that were done (i.e., (max 0 count)
)
to get the return value for the loop form. The loop is surrounded
by an implicit nil
block.
nil
, it loops over all symbols in
that obarray. For each symbol, the body forms are evaluated
with var bound to that symbol. The symbols are visited in
an unspecified order. Afterward the result form, if any,
is evaluated (with var bound to nil
) to get the return
value. The loop is surrounded by an implicit nil
block.
do-symbols
except that the obarray
argument is omitted; it always iterates over the default obarray.
See Mapping over Sequences, for some more functions for iterating over vectors or lists.