Common Lisp Extensions. Node: Iteration

PREV Blocks and Exits UP Control Structure NEXT Loop Facility

5.6: Iteration

The macros described here provide more sophisticated, high-level looping constructs to complement Emacs Lisp's basic while loop.

Special Form: loop forms...
The CL package supports both the simple, old-style meaning of 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.)

Special Form: do (spec...) (end-test [result...]) forms...
This macro creates a general iterative loop. Each spec is of the form
(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)))
Special Form: do* (spec...) (end-test [result...]) forms...
This is to 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))
Special Form: dolist (var list [result]) forms...
This is a more specialized loop which iterates across the elements of a list. list should evaluate to a list; the body forms are executed with var bound to each element of the list in turn. Finally, the result form (or 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.
Special Form: dotimes (var count [result]) forms...
This is a more specialized loop which iterates a specified number of times. The body is executed with var bound to the integers from zero (inclusive) to count (exclusive), in turn. Then the 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.
Special Form: do-symbols (var [obarray [result]]) forms...
This loop iterates over all interned symbols. If obarray is specified and is not 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.
Special Form: do-all-symbols (var [result]) forms...
This is identical to 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.

PREV Blocks and Exits UP Control Structure NEXT Loop Facility