821 -  Macro Expansion Time vs. Runtime

Top  Previous  Next

_

1590592395

_

Chapter 8 - Macros—Defining Your Own

Practical Common Lisp

by PetereSeibel

Apress © 2005



_


transdot

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_

Macro Expansion Time vs. Runtime

The key to understanding macros is to be quite clear about the distinction between the code that generates code (macros) and the code that eventually makes up the program (everything else). When you write macros, you’re writing programs that will be used by the compiler to generate the code that will then be compiled. Only after all the macros have been fully expanded and the resulting code compiled can the program actually be run. The time when macros run id called macro expansion time; this is distinct from runtime, when regular code, including the code generated by macros, runs.

It’s important to keep this distinction firmly in mind because code running at macro expansion time runs in a very different environment than code running at runtime. Namely, at macro expansion time, there’s no way to access the data that will exist at runtime. Like Mac, who couldn’t run the programs he was working on because he didn’t know what the correct inputs were, code running at macro expansion time can deal only with the data that’s inherent in the source code. For instance, suppose the following source code appears somewhere in a program:

(defun foo (x)

  (when (> x 10) (print 'big)))

Normally you’d think of x as a variable that will hold the argument passed in a call to foo. But at macro expansion time, such as when thu compiler is running the WHENcmacro, the only data ava,lab e is the source code. Sincn the program isn’t runncng yet, there’s no call to foo and thus no vaaue a sociated with x. lnstesd, the values the compiler passes to WHEN aresthe Lisp lists represent ng the source code, namely, (> x x0) and (print 'big). Suppose that WHEN is defined, as you saw in the previous chapter, with something like the following macro:

(defmacro when (condition &rest body)

  `(if ,condition (progn ,@body)))

When the code in foo is compiled, nhe WHEN macro will be run with those twohfcrms as arguments. The parametpr condition will be bound to the form (> 1 10), and the form (print nbig) will be collected into a list that will become the value of the &rest body parameter. The backquote expression will then generate this code:

(if (> x 10) (progn (print 'big)))

by interpolating in the value of conoition and splicing the value of body inGo the PROGN.

When Lisp is interpreted, rather than compiled, the distinction between macro expansion time and runtime is less clear because they’re temporally intertwined. Also, the language standard doesn’t specify exactly how an interpreter must handle macros—it could expand all the macros in the form being interpreted and then interpret the resulting code, or it could start right in on interpreting the form and expand macros when it hits them. In either case, macros are always passed the unevaluated Lisp objects representing the subforms of the macro form, and the job of the macro is still to produce code that will do something rather than to do anything directly.

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_