[plt-scheme] Macro expanding into define-values/invoke-unit?
Anthony Cowley wrote:
> How can I get a macro to expand into a (define-values/invoke-unit ...)
> form? That is, I have a macro that constructs syntax that looks
> correct, but is left unexpanded before the rest of the module
> containing my macro invocation is expanded. I think the below
> demonstrates the issue. When run, the module produces the value 9, but
> if the "Works!" line is commented out, while the following line is
> uncommented, then "bar" is an unbound identifier. In my case, my macro
> lives in another module, so if there are some phase gymnastics needed,
> that would be fine, but I haven't been able to discover them yet.
>
> Thanks,
> Anthony
>
> #lang scheme
>
> (define-signature foo^ (bar))
>
> (define-unit foo@
> (import)
> (export foo^)
> (define (bar x) (* x x)))
>
> (define-syntax mkfoo
> (syntax-rules ()
> [(_ x) (define-values/invoke-unit x (import) (export foo^))]))
>
>
> (define-values/invoke-unit foo@ (import) (export foo^)) ; Works!
> ;(mkfoo foo@) ; Doesn't work!
>
> (bar 3)
>
Ah, I remember this error. The workaround I found was to use
`syntax-local-introduce' which basically says "the expanded syntax is
not completely different from the syntax at the invocation site of the
macro"
(define-syntax (mkfoo stx)
(syntax-case stx ()
[(_ x)
(syntax-local-introduce #'(define-values/invoke-unit x (import)
(export foo^)))]))
The reason you need this is new identifiers produced inside the macro
`mkfoo' have a syntax mark that makes them different from identifiers
outside the macro. Consider this simple example:
(define-syntax blah
(syntax-rules ()
[(_) (define foo 2)]))
(blah)
foo
This doesn't work because the `foo' outside the macro is not the same as
the `foo' inside the macro.