[plt-scheme] macros: incompatible ellipsis match counts

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Feb 12 20:41:00 EST 2007

At Mon, 12 Feb 2007 20:16:04 -0500, Jon Rafkind wrote:
> 
> 
> Matthew Flatt wrote:
> > The rules for ellipses always take a while for me to page back in...
> >
> > At Mon, 12 Feb 2007 14:50:58 -0800 (PST), Ryan Culpepper wrote:
> >   
> >>> (define-syntax foo3
> >>>   (syntax-rules ()
> >>>     ((_ ((z ...) f ...) ...)
> >>>      (begin
> >>>        (begin
> >>>          (begin z f ...) ...)
> >>>        ...)
> >>>        )))
> >>>       
> >> This 'syntax-rules' expression is wrong. The 'z' pattern variable has
> >> an ellipsis-depth of 2, and the 'f' pattern variable also has an
> >> ellipsis-depth of 2. In the template, though, you're using 'f' at a
> >> depth of 3. Usually that kind of error is caught at compile time.
> >>     
> >
> > It's ok to have extra ellipses after a pattern variable in a template.
> > The rule is that the innermost ellipses are treated in the usual way,
> > and then the overall result is repeated as many times as necessary for
> > remaining ellipses (where the repeat count for each remaining ellipses
> > is determined by some other variable).
> >
> > Meanwhile, the count for each ellipses must be determined by at least
> > one pattern variable. Incompatible-count errors are possible if the
> > count is determined by more than one variable.
> >
> > In this case:
> >
> >         (begin
> >           (begin z f ...) ...)
> >         ...)
> >
> > The count for the first `...' is determined by `f', the count for the
> > second `...' is determined by both `z' and `(f ...)', and the count for
> > the last is determined by `(z ...)'.
> >
> >   
> I think you lose me right about here. Why does the last ellipses depend 
> on `(z ...)' and not `((z ...) f ...)' ?

Because the first two ellipses cover `f'. Whatever those two generate
for `f' will be repeated as many times as determined by `z'.

> I thought ... matched the 
> previous s-expression in its entirety.

Yes, but the last `...' is the 3rd one for `f', and so it just causes
repeats of whatever `(f ...) ...' generates.

> Also it feels to me like the second set of ellipses shouldn't depend on 
> both z and f.

But you just pointed out that `...' applies to everything before, which
in this case is `(z f ...)'. Neither `z' nor `f' is maxed out in
ellipses at `(z f ...)', so `...' attaches to both.

> Since f is already repeated in the begin the outer ... 
> should just repeat the begin for each z.

It could make sense to say that the first `...' applies to just `f',
the second applies to just `z' (with `(f ...)' results repeated), and
the last applies to both `z' and `f' --- and maybe that's what you want
in this case. Indeed, I suppose a more general template system would
let you annotate each `...' with the pattern variables on which it's
supposed to apply. Without those annotations, though, I don't see how
the template system would arrive at the mapping that you want.

The original template implementation in MzScheme had outer `...' taking
precedence over inner `...'. It worked, but it was less useful than
having inner `...' take precedence. So there is certainly some choice
in the automatic mapping, but some choices seem to be more useful than
others.

In any case, at some point maybe it's better to use `map'. :)

Matthew



Posted on the users mailing list.