我正在尝试编写一个宏生成宏,它生成的宏采用可变数量的参数.
我想知道是否有办法使以下代码工作:
(define-syntax-rule (greet name)
(define-syntax-rule (name args ...)
(printf "hello ~a~n" (list args ...))))
Run Code Online (Sandbox Code Playgroud)
现在,它说:"没有pattern variables之前ellipsis在template在:..."
如果我单独使用内部define-syntax-rule它可以正常工作,那么为什么当它由另一个宏生成时它不起作用?
这样做至少有3种"样式".
Soegaard 已经回答说你可以替换...身体中的每一个(... ...),因此它被解释为属于内部宏的文字省略号而不是属于外部宏的"元"省略号:
(define-syntax-rule (greet name)
(define-syntax-rule (name args (... ...))
(printf "hello ~a~n" (list args (... ...)))))
Run Code Online (Sandbox Code Playgroud)
优点:灵活,您可以在体内自由混合字面(... ...)和元...椭圆
缺点:如果你以前没见过(... ...),看起来很混乱
然而,放置(... <something>)一些东西并不仅限于此....如果你在那里放置一个完整的模板,那么...该模板中的任何一个也将被"引用",被视为文字而不是元,以同样的方式:
(define-syntax-rule (greet name)
(...
(define-syntax-rule (name args ...)
(printf "hello ~a~n" (list args ...)))))
Run Code Online (Sandbox Code Playgroud)
优点:如果你有更大的嵌套深度,你可能不需要((... ...) (... ...))像选项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>)
Run Code Online (Sandbox Code Playgroud)
您可以使用with #: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))))
Run Code Online (Sandbox Code Playgroud)
优点:灵活,您可以在体内自由混合字面ooo和元...椭圆.对我来说,它看起来不像是(... ...)或混淆((... ...) (... ...)).
缺点:对于更深层次的嵌套,您可能需要多个#:with定义,每个元级别一个定义.
在...属于外define-syntax-rule.为了在输出中生成省略号,您需要引用它(... ...).
(define-syntax-rule (greet name)
(define-syntax-rule (name args (... ...))
(printf "hello ~a~n" (list args (... ...)))))
Run Code Online (Sandbox Code Playgroud)
为了好玩:如果您需要编写一个生成宏的宏来生成宏,则需要((... ...) (... ...))生成省略号.