[plt-scheme] Macro expanding into define-values/invoke-unit?

From: Jon Rafkind (rafkind at cs.utah.edu)
Date: Sun Jul 12 19:33:35 EDT 2009

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.


Posted on the users mailing list.