[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Using Macros in Lisp



   Date: Fri, 8 Mar 91 13:10:53 -0500
   From: Andrew L. M. Shalit <alms@cambridge.apple.com>

   Consider the macro DOUBLE

   (defmacro double (number-form)
     `(+ ,number-form ,number-form))

   This yields

   (double 10)  ==>> (+ 10 10)

   But it also yields

   (double (incf foo))  ==>>  (+ (incf foo) (incf foo))

   In the second example, the expression (incf foo) is placed in the
   source code more than once, and so the side-effect of the expression
   happens more than once.  This probably isn't what was intended by the
   author of the macro or the user of the macro.

   To get around this, Common Lisp macros should ensure that value forms
   are evaluated once, and only once.

   A first cut would yield

   (defmacro double (number-form)
     `(let ((temp ,number-form))
	(+ temp temp)))

   But, of course, this fails because the use of the variable TEMP isn't
   hygenic.  So, to have the real version, we need to write:

   (defmacro double (number-form)
     (let ((number-var (make-variable "NUMBER")))
       `(let ((,number-var ,number-form))
	  (+ ,number-var ,number-var))))

All of which is why it is far better to write

(proclaim '(inline double))
(defun double (number)
  (+ number number))