我正在尝试编写一个宏生成宏,其中生成的宏带有可变数量的参数。
我想知道是否有一种方法可以使以下代码起作用:
(define-syntax-rule (greet name)
(define-syntax-rule (name args ...)
(printf "hello ~a~n" (list args ...))))
现在它说:“ pattern variables
中ellipsis
中template
前没有...
”
如果我自己使用内部的define-syntax-rule
可以正常工作,那么为什么当它是由另一个宏生成时却不能正常工作呢?
答案 0 :(得分:6)
至少有3种“样式”。
Soegaard already answered,您可以用...
替换正文中的每个(... ...)
,以便将其解释为属于内部宏的文字省略号,而不是“元”属于外部宏的省略号:
(define-syntax-rule (greet name)
(define-syntax-rule (name args (... ...))
(printf "hello ~a~n" (list args (... ...)))))
优势:灵活,您可以在体内自由混合文字(... ...)
和元...
椭圆
缺点:如果您以前没看过(... ...)
,看起来会感到困惑
但是,(... <something>)
周围的事物不仅限于...
。如果您在其中放置整个模板,则该模板中的所有...
都将被“引用”,以相同的方式视为文字而不是meta:
(define-syntax-rule (greet name)
(...
(define-syntax-rule (name args ...)
(printf "hello ~a~n" (list args ...)))))
优点:如果嵌套深度更大,则不需要((... ...) (... ...))
,而使用选项1则只需(... <something-containing (... <something>)>)
缺点:刚性,如果将(... <something>)
放在某物周围,则永远不能在该物内使用元省略号。您不能像使用样式1或3那样自由地混合文字和元椭圆。
这是另一种方式,我觉得不太混乱,但是它需要使用define-simple-macro
而不是define-syntax-rule
,以便可以使用#:with
绑定新的模式变量。
(require syntax/parse/define)
(define-simple-macro (<name> <arguments>)
#:with <pattern-variable> <expression>
<body-expression>)
您可以使用#:with
将ooo
模式变量绑定到文字省略号:#:with ooo (quote-syntax ...)
(require syntax/parse/define)
(define-simple-macro (greet name)
#:with ooo (quote-syntax ...)
(define-syntax-rule (name args ooo)
(printf "hello ~a~n" (list args ooo))))
优势:灵活,您可以在体内自由混合文字ooo
和元...
椭圆。在我看来,它看起来比(... ...)
或((... ...) (... ...))
少混乱。
缺点:为了更深层的嵌套,您可能需要多个#:with
定义,每个元级别一个。
答案 1 :(得分:5)
...
属于外部define-syntax-rule
。为了
要在输出中产生省略号,您需要用(... ...)
对其进行引用。
(define-syntax-rule (greet name)
(define-syntax-rule (name args (... ...))
(printf "hello ~a~n" (list args (... ...)))))
为了娱乐:如果您需要编写一个产生一个产生宏的宏的宏,则需要((... ...) (... ...))
产生一个省略号。