1
0
Fork 0
cl-sites/gigamonkeys.com/book/macros-standard-control-constructs.html

388 lines
30 KiB
HTML
Raw Normal View History

2023-10-25 11:23:21 +02:00
<HTML><HEAD><TITLE>Macros: Standard Control Constructs</TITLE><LINK REL="stylesheet" TYPE="text/css" HREF="style.css"/></HEAD><BODY><DIV CLASS="copyright">Copyright &copy; 2003-2005, Peter Seibel</DIV><H1>7. Macros: Standard Control Constructs</H1><P>While many of the ideas that originated in Lisp, from the conditional
expression to garbage collection, have been incorporated into other
languages, the one language feature that continues to set Common Lisp
apart is its macro system. Unfortunately, the word <I>macro</I> describes
a lot of things in computing to which Common Lisp's macros bear only a
vague and metaphorical similarity. This causes no end of
misunderstanding when Lispers try to explain to non-Lispers what a
great feature macros are.<SUP>1</SUP> To understand
Lisp's macros, you really need to come at them fresh, without
preconceptions based on other things that also happen to be called
macros. So let's start our discussion of Lisp's macros by taking a
step back and looking at various ways languages support extensibility.</P><P>All programmers should be used to the idea that the definition of a
language can include a standard library of functionality that's
implemented in terms of the &quot;core&quot; language--functionality that could
have been implemented by any programmer on top of the language if it
hadn't been defined as part of the standard library. C's standard
library, for instance, can be implemented almost entirely in portable
C. Similarly, most of the ever-growing set of classes and interfaces
that ship with Java's standard Java Development Kit (JDK) are written
in &quot;pure&quot; Java.</P><P>One advantage of defining languages in terms of a core plus a
standard library is it makes them easier to understand and implement.
But the real benefit is in terms of expressiveness--since much of
what you think of as &quot;the language&quot; is really just a library--the
language is easy to extend. If C doesn't have a function to do some
thing or another that you need, you can write that function, and now
you have a slightly richer version of C. Similarly, in a language
such as Java or Smalltalk where almost all the interesting parts of
the &quot;language&quot; are defined in terms of classes, by defining new
classes you extend the language, making it more suited for writing
programs to do whatever it is you're trying to do. </P><P>While Common Lisp supports both these methods of extending the
language, macros give Common Lisp yet another way. As I discussed
briefly in Chapter 4, each macro defines its own syntax, determining
how the s-expressions it's passed are turned into Lisp forms. With
macros as part of the core language it's possible to build new
syntax--control constructs such as <CODE><B>WHEN</B></CODE>, <CODE><B>DOLIST</B></CODE>, and
<CODE><B>LOOP</B></CODE> as well as definitional forms such as <CODE><B>DEFUN</B></CODE> and
<CODE><B>DEFPARAMETER</B></CODE>--as part of the &quot;standard library&quot; rather than
having to hardwire them into the core. This has implications for how
the language itself is implemented, but as a Lisp programmer you'll
care more that it gives you another way to extend the language,
making it a better language for expressing solutions to your
particular programming problems.</P><P>Now, it may seem that the benefits of having another way to extend
the language would be easy to recognize. But for some reason a lot of
folks who haven't actually used Lisp macros--folks who think nothing
of spending their days creating new functional abstractions or
defining hierarchies of classes to solve their programming
problems--get spooked by the idea of being able to define new
syntactic abstractions. The most common cause of macrophobia seems to
be bad experiences with other &quot;macro&quot; systems. Simple fear of the
unknown no doubt plays a role, too. To avoid triggering any
macrophobic reactions, I'll ease into the subject by discussing
several of the standard control-construct macros defined by Common
Lisp. These are some of the things that, if Lisp didn't have macros,
would have to be built into the language core. When you use them, you
don't have to care that they're implemented as macros, but they
provide a good example of some of the things you can do with
macros.<SUP>2</SUP> In the
next chapter, I'll show you how you can define your own macros. </P><A NAME="when-and-unless"><H2>WHEN and UNLESS</H2></A><P>As you've already seen, the most basic form of conditional
execution--if <I>x</I>, do <I>y</I>; otherwise do <I>z</I>--is provided by the
<CODE><B>IF</B></CODE> special operator, which has this basic form:</P><PRE>(if <I>condition</I> <I>then-form</I> [<I>else-form</I>])</PRE><P>The <I>condition</I> is evaluated and, if its value is non-<CODE><B>NIL</B></CODE>, the
<I>then-form</I> is evaluated and the resulting value returned.
Otherwise, the <I>else-form</I>, if any, is evaluated and its value
returned. If <I>condition</I> is <CODE><B>NIL</B></CODE> and there's no <I>else-form</I>,
then the <CODE><B>IF</B></CODE> returns <CODE><B>NIL</B></CODE>.</P><PRE>(if (&gt; 2 3) &quot;Yup&quot; &quot;Nope&quot;) ==&gt; &quot;Nope&quot;
(if (&gt; 2 3) &quot;Yup&quot;) ==&gt; NIL
(if (&gt; 3 2) &quot;Yup&quot; &quot;Nope&quot;) ==&gt; &quot;Yup&quot;</PRE><P>However, <CODE><B>IF</B></CODE> isn't actually such a great syntactic construct
because the <I>then-form</I> and <I>else-form</I> are each restricted to
being a single Lisp form. This means if you want to perform a
sequence of actions in either clause, you need to wrap them in some
other syntax. For instance, suppose in the middle of a spam-filtering
program you wanted to both file a message as spam and update the spam
database when a message is spam. You can't write this: </P><PRE>(if (spam-p current-message)
(file-in-spam-folder current-message)
(update-spam-database current-message))</PRE><P>because the call to <CODE>update-spam-database</CODE> will be treated as
the else clause, not as part of the then clause. Another special
operator, <CODE><B>PROGN</B></CODE>, executes any number of forms in order and
returns the value of the last form. So you could get the desired
behavior by writing the following:</P><PRE>(if (spam-p current-message)
(progn
(file-in-spam-folder current-message)
(update-spam-database current-message)))</PRE><P>That's not too horrible. But given the number of times you'll likely
have to use this idiom, it's not hard to imagine that you'd get tired
of it after a while. &quot;Why,&quot; you might ask yourself, &quot;doesn't Lisp
provide a way to say what I really want, namely, 'When <I>x</I> is true,
do this, that, and the other thing'?&quot; In other words, after a while
you'd notice the pattern of an <CODE><B>IF</B></CODE> plus a <CODE><B>PROGN</B></CODE> and wish for
a way to abstract away the details rather than writing them out every
time.</P><P>This is exactly what macros provide. In this case, Common Lisp comes
with a standard macro, <CODE><B>WHEN</B></CODE>, which lets you write this: </P><PRE>(when (spam-p current-message)
(file-in-spam-folder current-message)
(update-spam-database current-message))</PRE><P>But if it wasn't built into the standard library, you could define
<CODE><B>WHEN</B></CODE> yourself with a macro such as this, using the backquote
notation I discussed in Chapter 3:<SUP>3</SUP></P><PRE>(defmacro when (condition &amp;rest body)
`(if ,condition (progn ,@body)))</PRE><P>A counterpart to the <CODE><B>WHEN</B></CODE> macro is <CODE><B>UNLESS</B></CODE>, which reverses
the condition, evaluating its body forms only if the condition is
false. In other words: </P><PRE>(defmacro unless (condition &amp;rest body)
`(if (not ,condition) (progn ,@body)))</PRE><P>Admittedly, these are pretty trivial macros. There's no deep black
magic here; they just abstract away a few language-level bookkeeping
details, allowing you to express your true intent a bit more clearly.
But their very triviality makes an important point: because the macro
system is built right into the language, you can write trivial macros
like <CODE><B>WHEN</B></CODE> and <CODE><B>UNLESS</B></CODE> that give you small but real gains in
clarity that are then multiplied by the thousands of times you use
them. In Chapters 24, 26, and 31 you'll see how macros can also be
used on a larger scale, creating whole domain-specific embedded
languages. But first let's finish our discussion of the standard
control-construct macros. </P><A NAME="cond"><H2>COND</H2></A><P>Another time raw <CODE><B>IF</B></CODE> expressions can get ugly is when you have a
multibranch conditional: if <I>a</I> do <I>x</I>, else if <I>b</I> do <I>y</I>;
else do <I>z</I>. There's no logical problem writing such a chain of
conditional expressions with just <CODE><B>IF</B></CODE>, but it's not pretty.</P><PRE>(if a
(do-x)
(if b
(do-y)
(do-z)))</PRE><P>And it would be even worse if you needed to include multiple forms in
the then clauses, requiring <CODE><B>PROGN</B></CODE>s. So, not surprisingly, Common
Lisp provides a macro for expressing multibranch conditionals:
<CODE><B>COND</B></CODE>. This is the basic skeleton:</P><PRE>(cond
(<I>test-1</I> <I>form</I>*)
.
.
.
(<I>test-N</I> <I>form</I>*))</PRE><P>Each element of the body represents one branch of the conditional and
consists of a list containing a condition form and zero or more forms
to be evaluated if that branch is chosen. The conditions are
evaluated in the order the branches appear in the body until one of
them evaluates to true. At that point, the remaining forms in that
branch are evaluated, and the value of the last form in the branch is
returned as the value of the <CODE><B>COND</B></CODE> as a whole. If the branch
contains no forms after the condition, the value of the condition is
returned instead. By convention, the branch representing the final
else clause in an if/else-if chain is written with a condition of
<CODE><B>T</B></CODE>. Any non-<CODE><B>NIL</B></CODE> value will work, but a <CODE><B>T</B></CODE> serves as a
useful landmark when reading the code. Thus, you can write the
previous nested <CODE><B>IF</B></CODE> expression using <CODE><B>COND</B></CODE> like this: </P><PRE>(cond (a (do-x))
(b (do-y))
(t (do-z)))</PRE><A NAME="and-or-and-not"><H2>AND, OR, and NOT</H2></A><P>When writing the conditions in <CODE><B>IF</B></CODE>, <CODE><B>WHEN</B></CODE>, <CODE><B>UNLESS</B></CODE>, and
<CODE><B>COND</B></CODE> forms, three operators that will come in handy are the
boolean logic operators, <CODE><B>AND</B></CODE>, <CODE><B>OR</B></CODE>, and <CODE><B>NOT</B></CODE>.</P><P><CODE><B>NOT</B></CODE> is a function so strictly speaking doesn't belong in this
chapter, but it's closely tied to <CODE><B>AND</B></CODE> and <CODE><B>OR</B></CODE>. It takes a
single argument and inverts its truth value, returning <CODE><B>T</B></CODE> if the
argument is <CODE><B>NIL</B></CODE> and <CODE><B>NIL</B></CODE> otherwise.</P><P><CODE><B>AND</B></CODE> and <CODE><B>OR</B></CODE>, however, are macros. They implement logical
conjunction and disjunction of any number of subforms and are defined
as macros so they can <I>short-circuit</I>. That is, they evaluate only
as many of their subforms--in left-to-right order--as necessary to
determine the overall truth value. Thus, <CODE><B>AND</B></CODE> stops and returns
<CODE><B>NIL</B></CODE> as soon as one of its subforms evaluates to <CODE><B>NIL</B></CODE>. If all
the subforms evaluate to non-<CODE><B>NIL</B></CODE>, it returns the value of the
last subform. <CODE><B>OR</B></CODE>, on the other hand, stops as soon as one of its
subforms evaluates to non-<CODE><B>NIL</B></CODE> and returns the resulting value. If
none of the subforms evaluate to true, <CODE><B>OR</B></CODE> returns <CODE><B>NIL</B></CODE>. Here
are some examples:</P><PRE>(not nil) ==&gt; T
(not (= 1 1)) ==&gt; NIL
(and (= 1 2) (= 3 3)) ==&gt; NIL
(or (= 1 2) (= 3 3)) ==&gt; T</PRE><A NAME="looping"><H2>Looping</H2></A><P>Control constructs are the other main kind of looping constructs.
Common Lisp's looping facilities are--in addition to being quite
powerful and flexible--an interesting lesson in the
have-your-cake-and-eat-it-too style of programming that macros
provide.</P><P>As it turns out, none of Lisp's 25 special operators directly support
structured looping. All of Lisp's looping control constructs are
macros built on top of a pair of special operators that provide a
primitive goto facility.<SUP>4</SUP> Like many good abstractions,
syntactic or otherwise, Lisp's looping macros are built as a set of
layered abstractions starting from the base provided by those two
special operators.</P><P>At the bottom (leaving aside the special operators) is a very general
looping construct, <CODE><B>DO</B></CODE>. While very powerful, <CODE><B>DO</B></CODE> suffers, as
do many general-purpose abstractions, from being overkill for simple
situations. So Lisp also provides two other macros, <CODE><B>DOLIST</B></CODE> and
<CODE><B>DOTIMES</B></CODE>, that are less flexible than <CODE><B>DO</B></CODE> but provide
convenient support for the common cases of looping over the elements
of a list and counting loops. While an implementation can implement
these macros however it wants, they're typically implemented as
macros that expand into an equivalent <CODE><B>DO</B></CODE> loop. Thus, <CODE><B>DO</B></CODE>
provides a basic structured looping construct on top of the
underlying primitives provided by Common Lisp's special operators,
and <CODE><B>DOLIST</B></CODE> and <CODE><B>DOTIMES</B></CODE> provide two easier-to-use, if less
general, constructs. And, as you'll see in the next chapter, you can
build your own looping constructs on top of <CODE><B>DO</B></CODE> for situations
where <CODE><B>DOLIST</B></CODE> and <CODE><B>DOTIMES</B></CODE> don't meet your needs.</P><P>Finally, the <CODE><B>LOOP</B></CODE> macro provides a full-blown mini-language for
expressing looping constructs in a non-Lispy, English-like (or at
least Algol-like) language. Some Lisp hackers love <CODE><B>LOOP</B></CODE>; others
hate it. <CODE><B>LOOP</B></CODE>'s fans like it because it provides a concise way
to express certain commonly needed looping constructs. Its detractors
dislike it because it's not Lispy enough. But whichever side one
comes down on, it's a remarkable example of the power of macros to
add new constructs to the language. </P><A NAME="dolist-and-dotimes"><H2>DOLIST and DOTIMES</H2></A><P>I'll start with the easy-to-use <CODE><B>DOLIST</B></CODE> and <CODE><B>DOTIMES</B></CODE> macros.</P><P><CODE><B>DOLIST</B></CODE> loops across the items of a list, executing the loop body
with a variable holding the successive items of the
list.<SUP>5</SUP> This is the
basic skeleton (leaving out some of the more esoteric options):</P><PRE>(dolist (<I>var</I> <I>list-form</I>)
<I>body-form</I>*)</PRE><P>When the loop starts, the <I>list-form</I> is evaluated once to produce
a list. Then the body of the loop is evaluated once for each item in
the list with the variable <I>var</I> holding the value of the item. For
instance:</P><PRE>CL-USER&gt; (dolist (x '(1 2 3)) (print x))
1
2
3
NIL</PRE><P>Used this way, the <CODE><B>DOLIST</B></CODE> form as a whole evaluates to <CODE><B>NIL</B></CODE>.</P><P>If you want to break out of a <CODE><B>DOLIST</B></CODE> loop before the end of the
list, you can use <CODE><B>RETURN</B></CODE>.</P><PRE>CL-USER&gt; (dolist (x '(1 2 3)) (print x) (if (evenp x) (return)))
1
2
NIL</PRE><P><CODE><B>DOTIMES</B></CODE> is the high-level looping construct for counting loops.
The basic template is much the same as <CODE><B>DOLIST</B></CODE>'s. </P><PRE>(dotimes (<I>var</I> <I>count-form</I>)
<I>body-form</I>*)</PRE><P>The <I>count-form</I> must evaluate to an integer. Each time through the
loop <I>var</I> holds successive integers from 0 to one less than that
number. For instance:</P><PRE>CL-USER&gt; (dotimes (i 4) (print i))
0
1
2
3
NIL</PRE><P>As with <CODE><B>DOLIST</B></CODE>, you can use <CODE><B>RETURN</B></CODE> to break out of the loop
early.</P><P>Because the body of both <CODE><B>DOLIST</B></CODE> and <CODE><B>DOTIMES</B></CODE> loops can
contain any kind of expressions, you can also nest loops. For
example, to print out the times tables from <CODE>1 <20> 1 = 1</CODE> to
<CODE>20 <20> 20 = 400</CODE>, you can write this pair of nested <CODE><B>DOTIMES</B></CODE>
loops:</P><PRE>(dotimes (x 20)
(dotimes (y 20)
(format t &quot;~3d &quot; (* (1+ x) (1+ y))))
(format t &quot;~%&quot;))</PRE><A NAME="do"><H2>DO</H2></A><P>While <CODE><B>DOLIST</B></CODE> and <CODE><B>DOTIMES</B></CODE> are convenient and easy to use,
they aren't flexible enough to use for all loops. For instance, what
if you want to step multiple variables in parallel? Or use an
arbitrary expression to test for the end of the loop? If neither
<CODE><B>DOLIST</B></CODE> nor <CODE><B>DOTIMES</B></CODE> meet your needs, you still have access
to the more general <CODE><B>DO</B></CODE> loop.</P><P>Where <CODE><B>DOLIST</B></CODE> and <CODE><B>DOTIMES</B></CODE> provide only one loop variable,
<CODE><B>DO</B></CODE> lets you bind any number of variables and gives you complete
control over how they change on each step through the loop. You also
get to define the test that determines when to end the loop and can
provide a form to evaluate at the end of the loop to generate a
return value for the <CODE><B>DO</B></CODE> expression as a whole. The basic
template looks like this: </P><PRE>(do (<I>variable-definition</I>*)
(<I>end-test-form</I> <I>result-form</I>*)
<I>statement</I>*)</PRE><P>Each <I>variable-definition</I> introduces a variable that will be in
scope in the body of the loop. The full form of a single variable
definition is a list containing three elements.</P><PRE>(<I>var</I> <I>init-form</I> <I>step-form</I>)</PRE><P>The <I>init-form</I> will be evaluated at the beginning of the loop and
the resulting values bound to the variable <I>var</I>. Before each
subsequent iteration of the loop, the <I>step-form</I> will be evaluated
and the new value assigned to <I>var</I>. The <I>step-form</I> is optional;
if it's left out, the variable will keep its value from iteration to
iteration unless you explicitly assign it a new value in the loop
body. As with the variable definitions in a <CODE><B>LET</B></CODE>, if the
<I>init-form</I> is left out, the variable is bound to <CODE><B>NIL</B></CODE>. Also as
with <CODE><B>LET</B></CODE>, you can use a plain variable name as shorthand for a
list containing just the name.</P><P>At the beginning of each iteration, after all the loop variables have
been given their new values, the <I>end-test-form</I> is evaluated. As
long as it evaluates to <CODE><B>NIL</B></CODE>, the iteration proceeds, evaluating
the <I>statements</I> in order.</P><P>When the <I>end-test-form</I> evaluates to true, the <I>result-forms</I>
are evaluated, and the value of the last result form is returned as
the value of the <CODE><B>DO</B></CODE> expression.</P><P>At each step of the iteration the step forms for all the variables
are evaluated before assigning any of the values to the variables.
This means you can refer to any of the other loop variables in the
step forms.<SUP>6</SUP> That is, in a loop like this: </P><PRE>(do ((n 0 (1+ n))
(cur 0 next)
(next 1 (+ cur next)))
((= 10 n) cur))</PRE><P>the step forms <CODE>(1+ n)</CODE>, <CODE>next</CODE>, and <CODE>(+ cur next)</CODE>
are all evaluated using the old values of <CODE>n</CODE>, <CODE>cur</CODE>, and
<CODE>next</CODE>. Only after all the step forms have been evaluated are
the variables given their new values. (Mathematically inclined
readers may notice that this is a particularly efficient way of
computing the eleventh Fibonacci number.)</P><P>This example also illustrates another characteristic of
<CODE><B>DO</B></CODE>--because you can step multiple variables, you often don't
need a body at all. Other times, you may leave out the result form,
particularly if you're just using the loop as a control construct.
This flexibility, however, is the reason that <CODE><B>DO</B></CODE> expressions can
be a bit cryptic. Where exactly do all the parentheses go? The best
way to understand a <CODE><B>DO</B></CODE> expression is to keep in mind the basic
template.</P><PRE><B>(</B>do <B>(</B><I>variable-definition</I>*<B>)</B>
<B>(</B><I>end-test-form</I> <I>result-form</I>*<B>)</B>
<I>statement</I>*<B>)</B></PRE><P>The six parentheses in that template are the only ones required by
the <CODE><B>DO</B></CODE> itself. You need one pair to enclose the variable
declarations, one pair to enclose the end test and result forms, and
one pair to enclose the whole expression. Other forms within the
<CODE><B>DO</B></CODE> may require their own parentheses--variable definitions are
usually lists, for instance. And the test form is often a function
call. But the skeleton of a <CODE><B>DO</B></CODE> loop will always be the same.
Here are some example <CODE><B>DO</B></CODE> loops with the skeleton in bold: </P><PRE><B>(</B>do <B>(</B>(i 0 (1+ i))<B>)</B>
<B>(</B>(&gt;= i 4)<B>)</B>
(print i)<B>)</B></PRE><P>Notice that the result form has been omitted. This is, however, not a
particularly idiomatic use of <CODE><B>DO</B></CODE>, as this loop is much more
simply written using <CODE><B>DOTIMES</B></CODE>.<SUP>7</SUP></P><PRE>(dotimes (i 4) (print i))</PRE><P>As another example, here's the bodiless Fibonacci-computing loop:</P><PRE><B>(</B>do <B>(</B>(n 0 (1+ n))
(cur 0 next)
(next 1 (+ cur next))<B>)</B>
<B>(</B>(= 10 n) cur<B>))</B></PRE><P>Finally, the next loop demonstrates a <CODE><B>DO</B></CODE> loop that binds no
variables. It loops while the current time is less than the value of
a global variable, printing &quot;Waiting&quot; once a minute. Note that even
with no loop variables, you still need the empty variables list.</P><PRE><B>(</B>do <B>()</B>
<B>(</B>(&gt; (get-universal-time) *some-future-date*)<B>)</B>
(format t &quot;Waiting~%&quot;)
(sleep 60)<B>)</B> </PRE><A NAME="the-mighty-loop"><H2>The Mighty LOOP</H2></A><P>For the simple cases you have <CODE><B>DOLIST</B></CODE> and <CODE><B>DOTIMES</B></CODE>. And if
they don't suit your needs, you can fall back on the completely
general <CODE><B>DO</B></CODE>. What more could you want?</P><P>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 <CODE><B>LOOP</B></CODE> macro may give you an easier way to
express it.</P><P>The <CODE><B>LOOP</B></CODE> macro actually comes in two flavors--<I>simple</I> and
<I>extended</I>. The simple version is as simple as can be--an infinite
loop that doesn't bind any variables. The skeleton looks like this: </P><PRE>(loop
<I>body-form</I>*)</PRE><P>The forms in body are evaluated each time through the loop, which
will iterate forever unless you use <CODE><B>RETURN</B></CODE> to break out. For
example, you could write the previous <CODE><B>DO</B></CODE> loop with a simple
<CODE><B>LOOP</B></CODE>.</P><PRE>(loop
(when (&gt; (get-universal-time) *some-future-date*)
(return))
(format t &quot;Waiting~%&quot;)
(sleep 60))</PRE><P>The extended <CODE><B>LOOP</B></CODE> is quite a different beast. It's distinguished
by the use of certain <I>loop keywords</I> that implement a
special-purpose language for expressing looping idioms. It's worth
noting that not all Lispers love the extended <CODE><B>LOOP</B></CODE> language. At
least one of Common Lisp's original designers hated it. <CODE><B>LOOP</B></CODE>'s
detractors complain that its syntax is totally un-Lispy (in other
words, not enough parentheses). <CODE><B>LOOP</B></CODE>'s fans counter that that's
the point: complicated looping constructs are hard enough to
understand without wrapping them up in <CODE><B>DO</B></CODE>'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. </P><P>For instance, here's an idiomatic <CODE><B>DO</B></CODE> loop that collects the
numbers from 1 to 10 into a list:</P><PRE>(do ((nums nil) (i 1 (1+ i)))
((&gt; i 10) (nreverse nums))
(push i nums)) ==&gt; (1 2 3 4 5 6 7 8 9 10)</PRE><P>A seasoned Lisper won't have any trouble understanding that
code--it's just a matter of understanding the basic form of a <CODE><B>DO</B></CODE>
loop and recognizing the <CODE><B>PUSH</B></CODE>/<CODE><B>NREVERSE</B></CODE> idiom for building
up a list. But it's not exactly transparent. The <CODE><B>LOOP</B></CODE> version,
on the other hand, is almost understandable as an English sentence.</P><PRE>(loop for i from 1 to 10 collecting i) ==&gt; (1 2 3 4 5 6 7 8 9 10)</PRE><P>The following are some more examples of simple uses of <CODE><B>LOOP</B></CODE>.
This sums the first ten squares:</P><PRE>(loop for x from 1 to 10 summing (expt x 2)) ==&gt; 385</PRE><P>This counts the number of vowels in a string:</P><PRE>(loop for x across &quot;the quick brown fox jumps over the lazy dog&quot;
counting (find x &quot;aeiou&quot;)) ==&gt; 11</PRE><P>This computes the eleventh Fibonacci number, similar to the <CODE><B>DO</B></CODE>
loop used earlier: </P><PRE>(loop for i below 10
and a = 0 then b
and b = 1 then (+ b a)
finally (return a))</PRE><P>The symbols <CODE>across</CODE>, <CODE>and</CODE>, <CODE>below</CODE>,
<CODE>collecting</CODE>, <CODE>counting</CODE>, <CODE>finally</CODE>, <CODE>for</CODE>,
<CODE>from</CODE>, <CODE>summing</CODE>, <CODE>then</CODE>, and <CODE>to</CODE> are some of
the loop keywords whose presence identifies these as instances of the
extended <CODE><B>LOOP</B></CODE>. <SUP>8</SUP></P><P>I'll save the details of <CODE><B>LOOP</B></CODE> 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 <CODE><B>LOOP</B></CODE> 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 <CODE><B>LOOP</B></CODE> is regular Lisp
code. </P><P>And it's worth pointing out one more time that while the <CODE><B>LOOP</B></CODE>
macro is quite a bit more complicated than macros such as <CODE><B>WHEN</B></CODE>
or <CODE><B>UNLESS</B></CODE>, it <I>is</I> 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.</P><P>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.
</P><HR/><DIV CLASS="notes"><P><SUP>1</SUP>To see what this misunderstanding looks
like, find any longish Usenet thread cross-posted between
comp.lang.lisp and any other comp.lang.* group with <I>macro</I> in the
subject. A rough paraphrase goes like this:</P><P>Lispnik: &quot;Lisp is the best because of its macros!&quot;;</P><P>Othernik: &quot;You think Lisp is good <I>because of</I> macros?! But macros
are horrible and evil; Lisp must be horrible and evil.&quot;</P><P><SUP>2</SUP>Another important class of language constructs that are
defined using macros are all the definitional constructs such as
<CODE><B>DEFUN</B></CODE>, <CODE><B>DEFPARAMETER</B></CODE>, <CODE><B>DEFVAR</B></CODE>, 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.</P><P><SUP>3</SUP>You can't actually feed this
definition to Lisp because it's illegal to redefine names in the
<CODE>COMMON-LISP</CODE> package where <CODE><B>WHEN</B></CODE> comes from. If you really
want to try writing such a macro, you'd need to change the name to
something else, such as <CODE>my-when</CODE>.</P><P><SUP>4</SUP>The special operators, if you must
know, are <CODE><B>TAGBODY</B></CODE> and <CODE><B>GO</B></CODE>. There's no need to discuss them
now, but I'll cover them in Chapter 20.</P><P><SUP>5</SUP><CODE><B>DOLIST</B></CODE> is similar to Perl's <CODE>foreach</CODE> or
Python's <CODE>for</CODE>. Java added a similar kind of loop construct with
the &quot;enhanced&quot; <CODE>for</CODE> 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 &quot;expert group&quot; 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 <I>still</I> 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.</P><P><SUP>6</SUP>A variant of <CODE><B>DO</B></CODE>, <CODE><B>DO*</B></CODE>, assigns each
variable its value before evaluating the step form for subsequent
variables. For more details, consult your favorite Common Lisp
reference.</P><P><SUP>7</SUP>The <CODE><B>DOTIMES</B></CODE> is also
preferred because the macro expansion will likely include
declarations that allow the compiler to generate more efficient
code.</P><P><SUP>8</SUP><I>Loop keywords</I> is a bit of a misnomer
since they aren't keyword symbols. In fact, <CODE><B>LOOP</B></CODE> doesn't care
what package the symbols are from. When the <CODE><B>LOOP</B></CODE> macro parses
its body, it considers any appropriately named symbols equivalent.
You could even use true keywords if you wanted--<CODE>:for</CODE>,
<CODE>:across</CODE>, 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.</P></DIV></BODY></HTML>