I'm trying to create a simple nested macro. It works in my Scheme implementation, but fails to run in Guile and Racket.
(define-syntax foo
(syntax-rules (:c)
((_ x ...)
(let-syntax ((bar (syntax-rules ::: (:c)
((_ x)
(print x))
((_ a b :::)
(begin
(display a)
(display " ")
(bar b :::))))))
(bar x ...)))))
syntax: missing ellipsis
missing ellipsis with pattern variable in template
I've also tried to run in Gambit, but that one just throws:
Unbound variable: define-syntax
I guess you need to use a library to use a basic scheme.
In Checken Scheme, after updating ellipsis:
(define-syntax foo
(syntax-rules (:c)
((_ x ...)
(let-syntax ((bar (syntax-rules <:::> (:c)
((_ x)
(print x))
((_ a b <:::>)
(begin
(display a)
(display " ")
(bar b <:::>))))))
(bar x ...)))))
throws:
template dimension error (too few ellipses?): x
What's wrong with this macro? Why does it throw an error?
EDIT:
It seems that this pattern is not valid:
(_ x ...)
but this is
(_ x y ...)
Is this specified somewhere? Why the first syntax is not valid?
Just to be complete, this code compiles, but why the first doesn't?
(define-syntax foo
(syntax-rules ()
((_ x y ...)
(let-syntax ((bar (syntax-rules <:::> ()
((_ x)
(print x))
((_ a b <:::>)
(begin
(display a)
(display " ")
(bar b <:::>))))))
(bar x y ...)))))
But it doesn't work when tried to use foo
macro. It throws:
unbound variable: bar
even when using letrec-syntax
.
The problem is that ellipsis are following x
in your outer macro. This means the template that is produced should also have ellipsis following x
, which it doesn't. If you rename the inner macro's x
to y
it should work as you expect.
In other words, what you're doing here is equivalent to:
(define-syntax foo
(syntax-rules ()
((_ x ...)
(display x))))
Which wouldn't be allowed either. If you have x
with ellipsis in the pattern, you must also consume those ellipsis when consuming x
in the template that follows it.
The reason it works if you make it (x y ...)
is that y
(and its ellipsis rest) is not consumed at all by the template.