[plt-scheme] identifier-binding question
At Thu, 8 Jan 2009 12:26:11 +0100, "Jos Koot" wrote:
> #lang scheme
> (define-syntax (x stx)
> (syntax-case stx ()
> ((_ y)
> (let ((x (identifier-binding #'y)))
> (cond
> ((list? x) #''module)
> ((not x) #''top)
> ((eq? x 'lexical) #''lexical)
> (else #''unexpected))))))
> (x b) ; --> #f <== I expected `module' ???
> (define b 3)
> (x b) ; --> module
This has to do with the order of expansion. Within a module, top-level
forms are partially expanded in order that they appear. The partial
expansion goes far enough to determine whether the form is one of
* `require'
* `provide'
* `define-syntax'
* `define-for-syntax'
* `define'
* `begin' (body is spliced immediately)
* a core expression form
After the macro expander partially expands the module body, then all
bindings are known and everything left is an expression, and they are
expanded in a second pass.
So, in the above example, at the point where the first use of `x' is
being expanded, the `b' definition hasn't been seen, yet.
In practice, when `x' is an expression form, the solution is to expand
`(x b)' to `(#%expression (real-x b))', and put the real work in the
`real-x' form. That way, partial expansion of `(x b)' will expose that
it's an expression form without expanding the part that needs to have
all bindings available.
Matthew