Previous: , Up: Problems with Macros   [Contents][Index]


18.6.4 How Many Times is the Macro Expanded?

Occasionally problems result from the fact that a macro call is expanded each time it is evaluated in an interpreted function, but is expanded only once (during compilation) for a compiled function. If the macro definition has side effects, they will work differently depending on how many times the macro is expanded.

In particular, constructing objects is a kind of side effect. If the macro is called once, then the objects are constructed only once. In other words, the same structure of objects is used each time the macro call is executed. In interpreted operation, the macro is reexpanded each time, producing a fresh collection of objects each time. Usually this does not matter—the objects have the same contents whether they are shared or not. But if the surrounding program does side effects on the objects, it makes a difference whether they are shared. Here is an example:

(defmacro empty-object ()
  (list 'quote (cons nil nil)))
(defun initialize (condition)
  (let ((object (empty-object)))
    (if condition
        (setcar object condition))
    object))

If initialize is interpreted, a new list (nil) is constructed each time initialize is called. Thus, no side effect survives between calls. If initialize is compiled, then the macro empty-object is expanded during compilation, producing a single “constant” (nil) that is reused and altered each time initialize is called.

One way to avoid pathological cases like this is to think of empty-object as a funny kind of constant, not as a memory allocation construct. You wouldn’t use setcar on a constant such as '(nil), so naturally you won’t use it on (empty-object) either.


Previous: , Up: Problems with Macros   [Contents][Index]