8.2.1 Modules and Reusable Syntax Classes
As demonstrated in the Introduction, the simplest place to
define a syntax class is within the macro definition that uses it. But
this location, of course, limits the scope of the syntax class to the
one client macro. Creating reusable syntax classes is slightly
complicated, however, by the Racket phase level separation. A
syntax class defined within a module cannot be used by macros in the
same module; it is defined at the wrong phase.
|
syntax-parse: not defined as syntax class at: foo |
In the module above, the syntax class foo is defined at phase
level 0. The reference to foo within macro, however,
is at phase level 1, being the implementation of a macro
transformer. (Needing to require syntax/parse twice,
once normally and once for-syntax is another sign of the
phase level incompatibility.) The only way to define reusable syntax
classes that can be used within macros is to define them in a separate
module and require that module for-syntax.
|
|
> (require 'macro-mod) |
> (macro (1 2 3)) |
6 |
If the syntax classes refer to keywords, or if they compute
expressions via syntax templates, then the module containing the
syntax classes must generally require the keywords or bindings used in
the syntax templates for-template.
|
|
|
> (require 'arith-macro-mod) |
> (arith-macro (plus 1 (times 2 3))) |
'(+ 1 (* 2 3)) |
7 |
In 'arith-stxclass-mod, the module
'arith-keywords-mod must be required for-template
because the keywords are used in phase-0 expressions. Likewise, the
module racket must be required for-template
because the syntax class contains syntax templates involving
+ and * (and, in fact, the implicit #%app
syntax). All of these identifiers (the keywords plus and
times; the procedures + and *; and the
implicit syntax #%app) must be bound at “absolute” phase
level 0. Since the module 'arith-stxclass-mod is required
with a phase level offset of 1 (that is, for-syntax), it must
compensate with a phase level offset of -1, or for-template.