[plt-scheme] Confusion about lexical scoping, modules, and hygenic macros
At Tue, 16 Aug 2005 22:22:06 -0700 (PDT), Danny Yoo wrote:
> (define-syntax arrow
> (syntax-rules (->)
> [(arrow -> x)
^^
As you expect, this means "match an identifier same binding as `->'
here", which is to say, an identifier with no binding whose symbolic
name is `->'.
> However, the following gives a very surprising result:
>
> ;;;;;;
> > (module m3 mzscheme
> (require (lib "contract.ss"))
> (require m1)
> (display (arrow -> this-is-from-m3))
> (newline))
> repl-2:4:11: arrow: bad syntax in: (arrow -> this-is-from-m3)
> ;;;;;;
>
> I think I understand what's causing this. Somehow, during macro
> expansion, the macro system's convinced that '->' is lexically bound,
Yes. Within `m3', `->' is bound to a contract constructor by the import
of "contract.ss". So the `->' in the use of `arrow' does not match the
`->' in the definition.
> From the toplevel:
>
> ;;;;;;;;
> > (define -> 'blah)
> > (require m1)
> > (arrow -> 'ok-please-break)
> ((quote ok-please-break) is arrowed!)
The top level is hopeless. Since top-level identifiers might be
referenced before they are defined, there's no distinction at the top
level between "not bound" and "bound by a top-level variable".
Note that
> (define-syntax -> ...)
> (require m1)
> (arrow -> 'this-will-fail)
will produce a syntax error for the use of `arrow'. There's a
difference between "not bound" and "bound to top-level syntax" (and you
can't refer to a syntax binding before its definition at the top level).
Matthew