Macro
Ettiquette describes the science and art of using macros in Common
Lisp. By “science”, I mean the technical usage and mental model of how
Common Lisp macros work. By “art” I mean the principles of design that
you should consider when deciding whether or not to use macros.
There are good examples in this article. I’ve always wondered when
you might use a macro. The sine example was pretty convincing. It has
all the runtime benefits of hardcoding a lookup table, but you can
change the “coding” dynamically by changing the arguments of the macro
call and recompiling.
Highlights:
- Define a macro like a function, but instead of returning a value, it
returns a Lisp form
- Call a macro like a function, but know that it behaves differently.
Namely:
- Parameters to the macro call aren’t evaluated, but passed directly
to the body
- The macro expander (i.e. the body of the macro) is invoked and
returns a Lisp form
- Then Lisp runs the returned Lisp form
- Macros may be expanded at different times: compile time, first use,
each use, whatever
- One use case is to push computation into the compile step in order
to speed up the runtime
- Ex: Compute a sine lookup table at compile time so that runtime only
needs to lookup the corresponding value.
- Another use case is to expand the semantics of the language (macros
that define macros)
- Be careful with these - it’s easy to forget to recompile things that
depend on macros. >Ultimately, the likelihood that you’ll
inadvertently end up with code that was compiled with an old version of
a macro is directly proportional to how often you’re likely to change
the macro.
- Because macros involve form substituion, then evaluation,
you need to be aware of scope. Use GENSYM to avoid shadowing a variable.
- (This relates to unhygienic macros.)
- Common Lisp allows for inlining
- Rather than compiling a call to the function, the compiler may
substitute the function’s body. >My advice: Don’t use macros as a
substitute for inlining unless you can find no other way to achieve
desired performance