考虑两个宏的情况:outer-macro定义一些实体的一般结构,并inner-macro扩展外部宏的范围。以下代码捕获了我的意图,其中预期的输出是打印语句。本示例对内部宏的模式抛出以下错误:(_ value ...)。
syntax: no pattern variables before ellipsis in template in: ...
Run Code Online (Sandbox Code Playgroud)
我打算以与外部宏value ...的body ...模式相同的方式使用。实际上,“值”列表正是我所需要的(不一定是非常灵活的“省略号模式”)。遗憾的是,这种方式无法正常工作。如何捕获内部宏中可变数量的参数?
#lang racket
(require
racket/stxparam
(for-syntax syntax/parse))
(define-syntax-parameter inner-macro
(lambda (stx)
(raise-syntax-error 'inner-macro "generic error message" stx)))
(define-syntax (outter-macro stx)
(syntax-parse stx
[(_ body:expr ...+)
#'(syntax-parameterize
([inner-macro
(lambda (stx)
(syntax-case stx ()
[(_ value ...)
(printf "values are: ~a~n" (list value ...))]))])
body ...)]))
(outter-macro
(inner-macro 'a 'b 'c))
; expected result
; > "values are: (a b c)"
Run Code Online (Sandbox Code Playgroud)
亚历克西斯·金的答案很好。但是,我认为更简单的另一种实现方法是使用#:with模式(或with-syntax)来定义类似ooo文字省略号的内容。
您可以使用来创建文字省略号quote-syntax,因此#:with子句看起来像#:with ooo (quote-syntax ...)。然后,ooo无论何时要在宏的输出中生成省略号,都可以使用。
(define-syntax (outer-macro stx)
(syntax-parse stx
[(_ body:expr ...+)
#:with ooo (quote-syntax ...)
#'(syntax-parameterize
([inner-macro
(lambda (stx)
(syntax-case stx ()
[(_ value ooo)
#'(printf "values are: ~a~n" (list value ooo))]))])
body ...)]))
Run Code Online (Sandbox Code Playgroud)
要“逃避”语法模板中的省略号,可以使用语法(... <form>),其中<form>语法模板是...按字面意义对待的语法模板。因此,您可以包装一段语法以包括文字省略号:
> #'(... (syntax-rules ()
[(x ...) (list x ...)]))
#<syntax:4:9 (syntax-rules () ((x ...) (li...>
Run Code Online (Sandbox Code Playgroud)
您可以使用它来包围内部宏定义以转义内部椭圆:
(define-syntax (outer-macro stx)
(syntax-parse stx
[(_ body:expr ...+)
#'(syntax-parameterize
([inner-macro
(lambda (stx)
(... (syntax-case stx ()
[(_ value ...)
(printf "values are: ~a~n" (list value ...))])))])
body ...)]))
Run Code Online (Sandbox Code Playgroud)
但是,这实际上并不完全正确,因为您的syntax-case身体是错误的,它不会返回语法对象。您只是#'在(printf ...)(或可以使用syntax-rules)之前缺少,所以正确的实现应为以下内容:
(define-syntax (outer-macro stx)
(syntax-parse stx
[(_ body:expr ...+)
#'(syntax-parameterize
([inner-macro
(lambda (stx)
(... (syntax-case stx ()
[(_ value ...)
#'(printf "values are: ~a~n" (list value ...))])))])
body ...)]))
Run Code Online (Sandbox Code Playgroud)
这应该按预期工作。