The Mighty LOOP

For the simple cases you have **DOLIST** and **DOTIMES**. And if they don’t suit your needs, you can fall back on the completely general **DO**. What more could you want?

Well, it turns out a handful of looping idioms come up over and over again, such as looping over various data structures: lists, vectors, hash tables, and packages. Or accumulating values in various ways while looping: collecting, counting, summing, minimizing, or maximizing. If you need a loop to do one of these things (or several at the same time), the **LOOP** macro may give you an easier way to express it.

The **LOOP** macro actually comes in two flavors—simple and extended. The simple version is as simple as can be—an infinite loop that doesn’t bind any variables. The skeleton looks like this:

  1. (loop
  2. body-form*)

The forms in body are evaluated each time through the loop, which will iterate forever unless you use **RETURN** to break out. For example, you could write the previous **DO** loop with a simple **LOOP**.

  1. (loop
  2. (when (> (get-universal-time) *some-future-date*)
  3. (return))
  4. (format t "Waiting~%")
  5. (sleep 60))

The extended **LOOP** is quite a different beast. It’s distinguished by the use of certain loop keywords that implement a special-purpose language for expressing looping idioms. It’s worth noting that not all Lispers love the extended **LOOP** language. At least one of Common Lisp’s original designers hated it. **LOOP**‘s detractors complain that its syntax is totally un-Lispy (in other words, not enough parentheses). **LOOP**‘s fans counter that that’s the point: complicated looping constructs are hard enough to understand without wrapping them up in **DO**‘s cryptic syntax. It’s better, they say, to have a slightly more verbose syntax that gives you some clues what the heck is going on.

For instance, here’s an idiomatic **DO** loop that collects the numbers from 1 to 10 into a list:

  1. (do ((nums nil) (i 1 (1+ i)))
  2. ((> i 10) (nreverse nums))
  3. (push i nums)) ==> (1 2 3 4 5 6 7 8 9 10)

A seasoned Lisper won’t have any trouble understanding that code—it’s just a matter of understanding the basic form of a **DO** loop and recognizing the **PUSH**/**NREVERSE** idiom for building up a list. But it’s not exactly transparent. The **LOOP** version, on the other hand, is almost understandable as an English sentence.

  1. (loop for i from 1 to 10 collecting i) ==> (1 2 3 4 5 6 7 8 9 10)

The following are some more examples of simple uses of **LOOP**. This sums the first ten squares:

  1. (loop for x from 1 to 10 summing (expt x 2)) ==> 385

This counts the number of vowels in a string:

  1. (loop for x across "the quick brown fox jumps over the lazy dog"
  2. counting (find x "aeiou")) ==> 11

This computes the eleventh Fibonacci number, similar to the **DO** loop used earlier:

  1. (loop for i below 10
  2. and a = 0 then b
  3. and b = 1 then (+ b a)
  4. finally (return a))

The symbols across, and, below, collecting, counting, finally, for, from, summing, then, and to are some of the loop keywords whose presence identifies these as instances of the extended **LOOP**. 8

I’ll save the details of **LOOP** for Chapter 22, but it’s worth noting here as another example of the way macros can be used to extend the base language. While **LOOP** provides its own language for expressing looping constructs, it doesn’t cut you off from the rest of Lisp. The loop keywords are parsed according to loop’s grammar, but the rest of the code in a **LOOP** is regular Lisp code.

And it’s worth pointing out one more time that while the **LOOP** macro is quite a bit more complicated than macros such as **WHEN** or **UNLESS**, it is just another macro. If it hadn’t been included in the standard library, you could implement it yourself or get a third-party library that does.

With that I’ll conclude our tour of the basic control-construct macros. Now you’re ready to take a closer look at how to define your own macros.


1To see what this misunderstanding looks like, find any longish Usenet thread cross-posted between comp.lang.lisp and any other comp.lang.* group with macro in the subject. A rough paraphrase goes like this:

Lispnik: “Lisp is the best because of its macros!”;

Othernik: “You think Lisp is good because of macros?! But macros are horrible and evil; Lisp must be horrible and evil.”

2Another important class of language constructs that are defined using macros are all the definitional constructs such as **DEFUN**, **DEFPARAMETER**, **DEFVAR**, and others. In Chapter 24 you’ll define your own definitional macros that will allow you to concisely write code for reading and writing binary data.

3You can’t actually feed this definition to Lisp because it’s illegal to redefine names in the COMMON-LISP package where **WHEN** comes from. If you really want to try writing such a macro, you’d need to change the name to something else, such as my-when.

4The special operators, if you must know, are **TAGBODY** and **GO**. There’s no need to discuss them now, but I’ll cover them in Chapter 20.

5**DOLIST** is similar to Perl’s foreach or Python’s for. Java added a similar kind of loop construct with the “enhanced” for loop in Java 1.5, as part of JSR-201. Notice what a difference macros make. A Lisp programmer who notices a common pattern in their code can write a macro to give themselves a source-level abstraction of that pattern. A Java programmer who notices the same pattern has to convince Sun that this particular abstraction is worth adding to the language. Then Sun has to publish a JSR and convene an industry-wide “expert group” to hash everything out. That process—according to Sun—takes an average of 18 months. After that, the compiler writers all have to go upgrade their compilers to support the new feature. And even once the Java programmer’s favorite compiler supports the new version of Java, they probably still can’t use the new feature until they’re allowed to break source compatibility with older versions of Java. So an annoyance that Common Lisp programmers can resolve for themselves within five minutes plagues Java programmers for years.

6A variant of **DO**, **DO***, assigns each variable its value before evaluating the step form for subsequent variables. For more details, consult your favorite Common Lisp reference.

7The **DOTIMES** is also preferred because the macro expansion will likely include declarations that allow the compiler to generate more efficient code.

8Loop keywords is a bit of a misnomer since they aren’t keyword symbols. In fact, **LOOP** doesn’t care what package the symbols are from. When the **LOOP** macro parses its body, it considers any appropriately named symbols equivalent. You could even use true keywords if you wanted—:for, :across, and so on—because they also have the correct name. But most folks just use plain symbols. Because the loop keywords are used only as syntactic markers, it doesn’t matter if they’re used for other purposes—as function or variable names.