[plt-scheme] scope of module exports

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Mon Dec 11 14:27:14 EST 2006

Jon Rafkind skrev:
> I came across a, what I thought, strange situation with macros and 
> modules. If I provide an identifier that was created with 
> datum->syntax-object with macro A and define that identifier with macro 
> B then the module system will complain that the identifier is not 
> provided by the module. Basically this doesn't work:
> 
> (module x1 mzscheme
> 
> (define-syntax (b1 stx)
>  (syntax-case stx ()
>    ((_) (with-syntax ((f (datum->syntax-object #'stx 'foo)))
>       #'(define f 2)))))
> 
> (define-syntax (b2 stx)
>  (syntax-case stx ()
>    ((_) (with-syntax ((f (datum->syntax-object #'stx 'foo)))
>       #'(provide f)))))
> 
> (b1)
> (b2)
> )
> x.ss:1:0: module: provided identifier not defined or imported at: foo 
> in: (#%plain-module-begin (require-for-syntax mzscheme) (define-syntax 
> (b1 stx) (syntax-case stx () (...
> 
> I suppose because the provide statement in b2 doesn't see the variable 
> that was defined in b1. But if the syntax expansion phase happens before 
> the module evaluation phase then shouldn't this be ok? I guess I'm 
> missing something.

When is two identifiers "the same"?

In this case, I believe, you need the two foos to be
binding-identifier=?. Operationally this means that besides
having the same symbolic name, they must also have the same marks.
Thus they need to be introduced be the same macro use.

The section on provide in "PLT MzScheme: Language Manual" refers
to section 12.3.5:

   When a top-level definition binds an identifier that originates from a
   macro expansion, the definition captures only uses of the identifier
   that are generated by the same expansion. This behavior is consistent
   with internal definitions (see section 2.8.5), where the defined
   identifier turns into a fresh lexical binding.

Throwing hygiene overboard, you can use syntax-local-introduce to
avoid the expansion to add a mark to the identifier foo:

(module x1 mzscheme

   (define-syntax (b1 stx)
     (syntax-case stx ()
       ((_) (with-syntax
             ((f (syntax-local-introduce
                    (datum->syntax-object #'stx 'foo))))
              #'(define f 2)))))

   (define-syntax (b2 stx)
     (syntax-case stx ()
       ((_) (with-syntax
             ((f (syntax-local-introduce
                    (datum->syntax-object #'stx 'foo))))
              #'(provide f)))))

   (b1)
   (b2))

 > (require x1)
 > foo
2


-- 
Jens Axel Søgaard




Posted on the users mailing list.