Macros
categories: hacking
Description/Summary
Dive in MacrosContent
Papers
- Composable and Compilable Macros by Matthew Flatt, University of Utah
- Fortifying Macros by Ryan Culpepper & Matthias Felleisen, Northeastern University
Posts
- Practical macros in Racket and how to work with them by Kevin R. Stravers in 2017
- Fear of Macros by Greg Hendershott in 2020
- Why macros? by Greg Hendershott in 2014
Later I remembered Matthias Felleisen boiling down macros into three main categories:
Binding forms. You can make your own syntax for binding values to identifiers, including function definition forms. You may hear people say, in a Lisp you don’t have to wait for the language designers to add a feature (like
lambda
for Java?). Using macros you can add it yourself. Binding forms is one example.Changing order of evaluation. Something like
or
orif
can’t really be a function, because you want it to “short-circuit” — if the first test evaluates to true, don’t evaluate the other test at all.Abstractions like domain specific langagues (DSLs). You want to provide a special language, which is simpler and/or more task-specific than the full/raw Lisp you’re using. This DSL might be for users of your software, and/or it might be something that you use to help implement parts of your own program.
Every macro is doing one of those three things. Only macros can really do the first two, at all1. Macros let you do the last one more elegantly.
Rust
Racket
Emacs and orgmode
Lisp
- Lisp lang Macros
- Macro chapters from Practical Common Lisp:
- GNU Lisp macro
- GNU Emacs Lisp Macros
- Macros and Byte Compilation
When a macro call appears in a Lisp program being compiled, the Lisp compiler calls the macro definition just as the interpreter would, and receives an expansion. But instead of evaluating this expansion, it compiles the expansion as if it had appeared directly in the program. As a result, the compiled code produces the value and side effects intended for the macro, but executes at full compiled speed. This would not work if the macro body computed the value and side effects itself—they would be computed at compile time, which is not useful.
In order for compilation of macro calls to work, the macros must already be defined in Lisp when the calls to them are compiled. The compiler has a special feature to help you do this: if a file being compiled contains a defmacro form, the macro is defined temporarily for the rest of the compilation of that file.