[plt-scheme] scope of module exports
>> No, Jon just forgot that he needed stx not #'stx. [I communicated with him
>> directly.] -- Matthias
>>
> I've never really understood when to use quote in a macro, I have just
> been imitating code I see in the collects directory and I often see
> things like (datum->syntax-object #'name ...). Whats the difference
> between #'stx and stx when given to datum->syntax-object?
Hi Jon,
Let's look at a small example. In a clean DrScheme REPL:
;;;;;;;;;;;;;;;;
> (syntax hello)
#<syntax:3:10>
;;;;;;;;;;;;;;;;
If you open the snip up, you'll see 'hello' in there.
Compare this to:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> (with-syntax ([hello 'world])
(syntax hello))
#<syntax>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(Do this in DrScheme, and open up the snips. In MzScheme, the difference
is harder to see.)
When we use the syntax-handling forms (like SYNTAX-CASE or WITH-SYNTAX)
we're extending the syntactic environment. The expression:
(syntax <foo>)
is very much like quote, except that it respects the syntactic environment
that is built up with those syntax-handling forms above.
With that, let's look at one of the syntaxes that had an issue earlier:
(define-syntax (b2 stx)
(syntax-case stx ()
((_)
(with-syntax
((f (datum->syntax-object (syntax stx) 'foo)))
(syntax (provide f))))))
In the subexpression:
(datum->syntax-object (syntax stx) 'foo)
^^^^^^^^^^^^
we really want to introduce 'foo using the syntax object stx in the
regular environment. That is, we want the one from:
(define-syntax (b2 stx) ...)
^^^
and that's the 'stx' we want for our call to DATUM->SYNTAX-OBJECT.
That's why (syntax stx) is inappropriate: stx isn't bound in the syntax
environment. In that case, (SYNTAX STX) creates a fresh syntax object
that bears no relation to the input syntax object, and that's why your
macro broke.
By the way, one way to make this work might be to rebind 'stx' in the
syntactic environment:
(define-syntax (b2 stx)
(syntax-case stx ()
(stx-rebound
(with-syntax
((f (datum->syntax-object (syntax stx-rebound) 'foo)))
(syntax (provide f))))))
In which case, (SYNTAX STX-REBOUND) refers to the binding introduced by
the SYNTAX-CASE. But this is more verbose. Or we could be intentionally
obscure by doing:
(define-syntax (b2 stx)
(syntax-case stx ()
(stx
(with-syntax
((f (datum->syntax-object (syntax stx) 'foo)))
(syntax (provide f))))))
where we now have bindings of stx in both the normal and the syntactic
environment. But this is just trying to confuse people. *grin*
The resources at:
http://home.comcast.net/~prunesquallor/macro.txt
and the other stuff in:
http://schemecookbook.org/Cookbook/GettingStartedMacros
are helpful. Best of wishes!