Course
Grades
Email
Welcome
Policies
Grades
Inc
Intgrty
Preface
Part I
Chap 1
Chap 2
Chap 3
XEmacs
Chap 4
Chap 5
Chap 6
Chap 7
Chap 8
Chap 9
Part II
Chap 10
Chap 11
Chap 12
Chap 13
Chap 14
Chap 15
Chap 16
Chap 17
Chap 18
Chap 19
Chap 20
Chap 21
Chap 22
Chap 23
Part III
Chap 24
Chap 25
Chap 26
Chap 27
Chap 28
Chap 29
Chap 30
Chap 31
Chap 32
|
CHAPTER 23: MACROS
- Corrections
-
- Page 171, line 7: Change its to it has
- Page 171, line -9: Change (macroexpand
'(pluslist-f (+ 3 4) 5)) to (macroexpand '(pluslist-m (+ 3 4) 5)).
- Notes
-
- Read Chapter 23 in conjunction with these notes. Be warned:
students in the past have found this chapter difficult.
- A way to think about programming with macros is to think of
it as programming with patterns. Consider the
if defined
on page 169 of the text. It will be called with a form looking like
(if condition then then-clause else else-clause)
and what we really want this form to act like is
(lisp:if condition then-clause else-clause)
So, the body of the macro will be the form we want, quoted with the
backquote, and with every lambda variable in the form preceded with a
comma:
`(lisp:if ,condition ,then-clause ,else-clause)
- Let's consider the function
equal defined in
the notes to Chapter 20, and see how to
define it as a macro. This is the best technique for making use of a
two-argument function to define a version of it that takes an
arbitrary number of arguments. We will start the same way, but this
time make equal a macro.
(defmacro equal (object1 object2 &rest more-objects)
"Returns True if all the objects are lisp:equal;
False, otherwise."
_____
)
Now, if more-objects is NIL , (equal
object1 object2) can just be turned into
(lisp:equal object1 object2) :
(defmacro equal (object1 object2 &rest more-objects)
"Returns True if all the objects are lisp:equal;
False, otherwise."
(if (null more-objects)
`(lisp:equal ,object1 ,object2)
_____)
)
If there are more-objects , we could first test whether
object1 is lisp:equal to
object2 , and then test whether object2 and
all the other objects are equal . That is, we want
to turn
(equal object1 object2 object3 ...)
into
(and (lisp:equal object1 object2)
(equal object2 object3 ...))
A first attempt at a form which, put into the body of the macro, would
evaluate to this form is
`(and (lisp:equal ,object1 ,object2)
(equal ,object2 ,more-objects))
but this would expand into
(and (lisp:equal object1 object2)
(equal object2 (object3 ...)))
because more-objects is a list of the other objects.
This is exactly what the ,@ option inside a backquote is
for---to splice a list into an enclosing list. So our final version
of the equal macro is
(defmacro equal (object1 object2 &rest more-objects)
"Returns True if all the objects are lisp:equal;
False, otherwise."
(if (null more-objects)
`(lisp:equal ,object1 ,object2)
`(and (lisp:equal ,object1 ,object2)
(equal ,object2 ,@more-objects))))
Try defining ch23::equal this way (shadowing
lisp:equal , and test it.
- Create a file named
ch23.cl , and in it define the
function ch23::union (shadowing
common-lisp:union ), as described in the notes to Chapter 20. However, use the techniques
of Chapter 23 instead of the techniques of Chapter 20 or of Chapter
22. Submit this file.
|