syntax-case macros have the whole power of Scheme available to them,
they present a problem regarding time: when a macro runs, what parts of the
program are available for the macro to use?
The default answer to this question is that when you import a module (via
use-modules), that module will be loaded up at
expansion-time, as well as at run-time. Additionally, top-level syntactic
definitions within one compilation unit made by
define-syntax are also
evaluated at expansion time, in the order that they appear in the compilation
But if a syntactic definition needs to call out to a normal procedure at expansion-time, it might well need need special declarations to indicate that the procedure should be made available at expansion-time.
For example, the following code tries to embed a compilation timestamp in the compiled bytecode using a macro that expands to the date as a string literal. It will work at a REPL, but not in a file, as it cannot be byte-compiled:
(use-modules (srfi srfi-19)) (define start-date (date->string (current-date))) (define-syntax *compilation-date* (lambda (sintax) start-date)) (display *compilation-date*) (newline)
It works at a REPL because the expressions are evaluated one-by-one, in order, but if placed in a file, the expressions are expanded one-by-one, but not evaluated until the compiled file is loaded.
The fix is to use
(use-modules (srfi srfi-19)) (eval-when (expand load eval) (define start-date (date->string (current-date)))) (define-syntax *compilation-date* (lambda (sintax) start-date)) (display *compilation-date*) (newline)
Evaluate exp... under the given conditions. Valid conditions include:
Evaluate during macro expansion, whether compiling or not.
Evaluate during the evaluation phase of compiled code, e.g. when loading a compiled module or running compiled code at the REPL.
Evaluate during the evaluation phase of non-compiled code.
Evaluate during macro expansion, but only when compiling.
In other words, when using the primitive evaluator,
expand are run during macro expansion, and those
eval are run during the evaluation phase.
When using the compiler,
eval-when expressions with either
compile are run during macro expansion, and
load are run during the evaluation phase.
When in doubt, use the three conditions
(expand load eval), as in
the example above. Other uses of
eval-when may void your
warranty or poison your cat.