Next: , Previous: Top, Up: Top


1 Introduction

This manual describes iterate, a powerful iteration facility for Common Lisp. iterate provides abstractions for many common iteration patterns and allows for the definition of additional patterns. iterate is a macro that expands into ordinary Lisp at compile-time, so it is more efficient than higher-order functions like map and reduce. While it is similar to loop, iterate offers a more Lisp-like syntax and enhanced extensibility. (For a more complete comparison of iterate with other iteration constructs, see MIT AI Lab Working Paper No. 324, Don't Loop, Iterate. also included in this manual in Don't Loop Iterate.)

An iterate form consists of the symbol iter1 followed by one or more forms, some of which may be iterate clauses. Here is a simple example of iterate which collects the numbers from 1 to 10 into a list, and returns the list. The return value is shown following the arrow.

  (iter (for i from 1 to 10)
        (collect i))          => (1 2 3 4 5 6 7 8 9 10)

This form contains two clauses: a for clause that steps the variable i over the integers from 1 to 10, and a collect clause that accumulates its argument into a list. With a few exceptions, all iterate clauses have the same format: alternating symbols (called keywords) and expressions (called arguments). The syntax and terminology are those of Common Lisp's keyword lambda lists. One difference is that iterate's keywords do not have to begin with a colon—though they may, except for the first symbol of a clause. So you can also write (for i :from 1 :to 10) if you prefer.

Any Lisp form can appear in the body of an iterate, where it will have its usual meaning. iterate walks the entire body, expanding macros, and recognizing clauses at any level. This example collects all the odd numbers in a list:

  (iter (for el in list)
        (if (and (numberp el) (oddp el))
            (collect el)))

There are clauses for iterating over numbers, lists, arrays and other objects, and for collecting, summing, counting, maximizing and other useful operations. iterate also supports the creation of new variable bindings, stepping over multiple sequences at once, destructuring, and compiler declarations of variable types. The following example illustrates some of these features:

  (iter (for (key . item) in alist)
        (for i from 0)
        (declare (fixnum i))
        (collect (cons i key)))

This loop takes the keys of an alist and returns a new alist associating the keys with their positions in the original list. The compiler declaration for i will appear in the generated code in the appropriate place.


Footnotes

[1] You can also use iterate, but iter is preferred because it avoids potential conflicts with possible future additions to Common Lisp, and because it saves horizontal space when writing code.