[plt-scheme] scope of module exports

From: Danny Yoo (dyoo at hkn.eecs.berkeley.edu)
Date: Tue Dec 12 17:28:40 EST 2006

>> 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!


Posted on the users mailing list.