[plt-scheme] identifier-binding question

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Thu Jan 8 08:11:17 EST 2009

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.


Posted on the users mailing list.