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.
  
  
  
  |