Matthias has long promoted the four primary families of applications for macros as
- providing cosmetics
- introducing binding constructs
- implementing control operators (i.e., altering the order of evaluation)
- defining data languages
His paper deals particularly with the fourth use, defining data languages. And he makes the following insight:
The sub-terms of a macro invocation can contain arbitrary phrases, some of which may not even be legitimate Scheme code. In such cases, the macro construct is essentially creating an abstraction over an implementation choice. For instance, suppose a particular datum can be represented either as a procedure or as a structure.When an embedded language is implemented as a macro, the user may in fact have no idea what parts are implemented as binding forms in the implementation. The automaton example is a perfect demonstration: you might choose to implement the names of states as symbols in an association list, or you might choose to implement them as binding mutually (tail-)recursive local procedures. In this example, your user shouldn't know what your implementation decision was, and certainly shouldn't have to know.
This is one place where the distinction between macros as language extensions and macros as embedded languages becomes significant. When you add a feature to Scheme, your user needs to know about its binding properties. By contrast, when you implement a different language in Scheme, your user thinks about the semantics of the embedded language, rather than the semantics of its implementation language.