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 iter
1
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.
[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.