[plt-scheme] Null syntax / Conditional definition
At Mon, 20 Jun 2005 01:53:37 +0900, Chihiro Kuraya wrote:
> -----------------------------------------------------------------------
> (module m1 mzscheme
> (provide if-for-syntax)
> (define-syntax (if-for-syntax stx)
> (syntax-case stx ()
> ((_ TEST THEN ELSE)
> (if (eval #'TEST)
> #'THEN
> #'ELSE))))
> )
>
> (module m2 mzscheme
> (require m1)
> (define OS 'windows)
>
> (if-for-syntax (eq? OS 'windows)
> (begin
> (define OS-name "Windows"))
> (begin
> (define OS-name "Unknown")))
> )
> -----------------------------------------------------------------------
>
> But the following error message was displayed.
>
> -----------------------------------------------------------------------
> require: broken compiled code (phase 0, defn-phase 0):
> cannot find module m2 in: OS
> -----------------------------------------------------------------------
>
> I can't understand why this code doesn't work
> and what means this error message.
>
> Doesn't #'TEST syntax object have lexical context which
> contains OS identifier ?
The identifier `OS' does not correspond to a binding until the module
`m' is evaluated, and the module `m' is not evaluated until after all
of it's expressions are expanded. In other words, there's a phase
separation between compile time (when the module is expanded) and run
time (when the module is executed and its internal bindings exist).
The error message from `eval' is not great, but `eval' provides an
inherently strange bridge between phases. Just avoid `eval'.
The code below shows how to do what you want (I think) in a
phase-friendly manner. The `OS' binding is a for-syntax binding, so it
can be used at compile time. The `if-for-syntax' macro expands so that
the test ends up in a compile-time position that selects the THEN or
ELSE run-time branch. (The intermediate `result' macro essentially
plays the role of a compile-time `eval', but it explicitly shifts the
expression to compile time.)
Matthew
----------------------------------------
(module m1 mzscheme
(provide if-for-syntax)
(define-syntax (if-for-syntax stx)
(syntax-case stx ()
((_ TEST THEN ELSE)
#'(begin
(define-syntax (result stx)
(syntax-case stx ()
[(_ t e)
(if TEST
#'t
#'e)]))
(result THEN ELSE)))))
)
(module m2 mzscheme
(require m1)
(define-for-syntax OS 'windows)
(if-for-syntax (eq? OS 'windows)
(begin
(define OS-name "Windows"))
(begin
(define OS-name "Unknown")))
)