[R6RS] syntax-case

dyb at cs.indiana.edu dyb
Tue Apr 12 11:32:40 EDT 2005


> > In syntax-case or syntax-rules, you name the variable(s) that precede
> > the ellipses, so you would give different names for gee and hux, i.e.,
> > 
> >   (define-syntax foo
> >     (syntax-rules ()
> >       ((_ (bar1 (gee1 (hux1 ...) ...) ...)
> >           (bar2 (gee2 (hux2 ...) ...) ...))
> >        SOMETHING THAT USES ALL THE ELLIPSES
> >       ---))
> But this prevents from matching possibly empty lists.

Maybe I'm missing what you mean, but <pat> ... matches zero or more
<pat>s, So (hux1 ...) matches an empty list, (gee1 (hux1 ...) ...) matches
an empty list, and (bar1 (gee1 (hux1 ...) ...) ...) matches an empty list.

> > Do your named ellipses always follow a single pattern variable, or
> > can they follow a subform containing multiple pattern variables which
> > can then be separated in the output, as in the following syntax-rules
> > definition for (unnamed) let?
> Named ellipses can be used anywhere without restrictions. I think that this
> is more powerful even though it might be more verbose in the context of
> macros.

It's not more powerful for writing syntactic extensions, where one has
to wrap the output in a syntax form anyway, and it's less powerful there
since you have to do the mapping explicitly, as your examples illustrate.

> > (define-syntax let
> >   (syntax-rules ()
> >     ((_ ((x e) ...) b1 b2 ...)
> >      ((lambda (x ...) b1 b2 ...) e ...))))
> This example should be written:
>
>   (match-case x
>     ((?- ?bindings . ?body)
>      `((lambda ,(map car bindings) , at body) ,(map cadr bindings))))

So you have to do the mapping explicitly.  I certainly prefer not to
have to do so.

> > Also, how would you write the following macro, which requires that one of
> > the inputs (k) and an introduced identifier (*) be replicated as needed
> > to match the number of subforms e ...?
> > 
> > (define-syntax distr
> >   (syntax-rules ()
> >     ((_ k e ...)
> >      (+ (* k e) ...))))
> > (distr n a b c) -> (+ (* n a) (* n b) (* n c))
>   (match-case x
>      ((distr ?k . ?rest)
>       `(+ ,@(map (lambda (r) `(* ,k ,r)) rest))))

Again, I prefer the version that does not involve explicit mapping.

> >  Here's how I might write something similar using syntax-case in Chez Scheme.
> > 
> > (define-syntax +
> >   (lambda (x)
> >     (import scheme) ; so we can use the built-in +
> >     (syntax-case x ()
> >       [(_) 0]
> >       [(_ x) #'x]
> >       [(_ x y)
> >        (and (integer? (datum x)) (integer? (datum y)))
> >        (+ (datum x) (datum y))]
> >       [(k x m ...) #'(+ x (k m ...))])))
> How is the macro expansion prevented from falling into a infinite loop
> while expansing (+ x y) (due to the last clause that introduces a new
> (+ ...)). I'm missing something here.

The (import scheme) makes the built-in + visible, so that the two
occurrences of + in the syntax-case form refer to the built-in +.
The macro plucks the keyword identifier out of the input (as k) to use
for recursion.

Kent


More information about the R6RS mailing list