Page 162
nil!
Exercise for the reader: what's the difference between Graham's
nil!
and the following:
(defun set-nil (x) (setf x nil))
Page 163
Macro functions
The comment at the top of the page about macros being functions is
confusing. Macros are not functions, so you can't pass a macro
to apply
, mapcar
, etc.
However, macros work by calling macro expanders to expand the
macro call into Lisp code. Macro expanders are functions. You
can get the macro expander for a macro using
macro-function
.
Page 165
rotatef
Why is the macro that swaps two variables called
rotatef
? Well, the f
part is by analogy to
setf
. rotatef
operates on "places" just
like setf
does. The rotate
part is because
rotatef
can handle any number of places, not just two.
See the glossary in Graham for details.
Quicksort
If you do
the list-of
macro exercise,
then you can define
quicksort
on a list (not a vector) like this:
(defun quicksort (l) (cond ((null l) nil) (t (let ((p (car l)) (r (cdr l))) (append (quicksort (list-of x (x :in r) (< x p))) (list p) (quicksort (list-of x (x :in r) (>= x p))))))))
This is pretty inefficient (it conses a lot), but it does capture the essence of the algorithm nicely: choose a pivot p and split the list into those items less than p and greater than p.
Page 169
Graham's append1f
example is not portable. On this
page and in the glossary, he correctly says that define-modify-macro
requires a function name. Why he then used a lambda
I can't say.
Page 172
avg
This is a cute example of compile-time optimization but it's also an example of an evil macro.