[plt-scheme] scope of module exports
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