[plt-scheme] macros: incompatible ellipsis match counts
Matthew Flatt wrote:
> 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.
>
>
Is it more concise to say that the number of z's has to match the number
of f ...'s for the same reason the number of z's has to match the number
of f's in the following macro
(define-syntax foo
((_ (z ...) (f ...))
(begin (begin z f) ...))))
I played with the macro a little more and added yet another set of ellipses
(define-syntax foo3
(syntax-rules ()
((_ (((z ...) f ...) ...) ...)
(begin
(begin
(begin
(begin z f ...) ...)
...)
...)
)))
(foo3 (((1 2 3) 4 5 6) ((1 2 3) 1) ((1 2 3) 1 2))
(((1 2 3) 4 5 6) ((1 2 3) 1) ((1 2 3) 1 2))
(((1 2 3) 4 5 6) ((1 2 3) 1) ((1 2 3) 1 2)))
(foo3 (((1 2) 4 5 6) ((1 2) 1))
(((1 2) 4 5 6) ((1 2) 1)))
You can see that the number of z's determine the number of rows and
columns, because the number of z's has to equal the number of f ...
expressions and f ... .... expressions, or maybe the number of z ...
expressions has to equal the number of f ... ... expressions, I'm not
exactly sure but the z's definately determine the rest anyway.
> 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'. :)
>
>
Probably. This whole example is somewhat artificial.. I was explaning
macros to a friend and this stumped me.