[plt-scheme] an issue with macros expanding to transformers
An explanation for why you need a `(meta -1)' binding for your macro:
(define-syntax make-transformer
(syntax-rules ()
((_ (name value) ...) (syntax-rules (<names> name ...)
((_ <names>) '(name ...))
((_ name) value) ...))))
)
When you move to the right-hand side of `define-syntax', then the
relevant binding level is more more than the context of the definition.
So, if we start from 0, then we move to 1 for the outer `syntax-rules'.
That should be as expected; you're using `syntax-rules' in an
expand-time position.
When you go into a template, as in the right-hand side of a
`syntax-rules' clause, then you go back down one phase level. So from 1
for the outer `syntax-rules', we'd go back down to 0 for the binding of
the inner `syntax-rules'. (A `for ... expand' import will shift this
back up to phase level 1.)
Unusually in this case, the content of the template is itself a
`syntax-rules', which has its own templates. We go down one more level
for the nested template that contains a quote. That is, we go from
level 0 for the inner `syntax-rules' to level -1 for the quote. (Again,
a `for ... expand' import shifts it back to phase level 0, which
corresponds to run-time of the importing module.)
So, the macro needs a binding for `quote' at phase level -1.
At Mon, 02 Mar 2009 08:39:20 -0700, Chongkai Zhu wrote:
> The following works on my computer:
>
>
> #!r6rs
> (library (helper)
>
> (export make-transformer)
> (import (rnrs) (for (rnrs) (meta -1)))
>
> (define-syntax make-transformer
> (syntax-rules ()
> ((_ (name value) ...)
> (syntax-rules (<names> name ...)
> ((_ <names>) '(name ...))
> ((_ name) value) ...))))
> )
>
> Chongkai
>
> Michele Simionato wrote:
> > While porting some macros from Ikarus to PLT Scheme I found out an
> > issue
> > that baffles me.
> > Here is the simplified version of the problem. I want to define a
> > second
> > order macro, i.e. a macro which expands to a macro transformer.
> > So I put in a helper module the following make-transformer macro:
> >
> > #!r6rs
> > (library (helper)
> > (define-syntax make-transformer
> > (syntax-rules ()
> > ((_ (name value) ...) (syntax-rules (<names> name ...)
> > ((_ <names>) '(name ...))
> > ((_ name) value) ...))))
> > )
> >
> > Then I tried to use it in a script as follows:
> >
> > #!r6rs
> > (import (rnrs) (for (helper) expand))
> >
> > (define-syntax m (make-transformer (x 1) (y 2)))
> > (display (m x))
> > (display (m y))
> > (display (m <names>))
> >
> > In theory the macro m should be equivalent to
> >
> > (define-syntax m (syntax-rules (<names> x y)
> > ((_ <names>) '(x y))
> > ((_ x) 1)
> > ((_ y) 2)))
> >
> > and actually (m x) returns 1 and (m y) returns 2 as expected.
> > However, (m <names>) does not return '(x y) as it should;
> > instead I get an error:
> >
> > compile: bad syntax; function application is not allowed, because no #
> > %app syntax transformer is bound in: (quote (x y))
> >
> > (tested in PLT 4.0). How am I supposed to solve this?
> > TIA,
> >
> > Michele Simionato
> > _________________________________________________
> > For list-related administrative tasks:
> > http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> >
>
> _________________________________________________
> For list-related administrative tasks:
> http://list.cs.brown.edu/mailman/listinfo/plt-scheme