考虑两个宏的场景:outer-macro
定义某个实体的一般结构,inner-macro
扩展到外部宏的范围。我的意图在以下代码中捕获,其中预期输出是print语句。此示例为内部宏的模式抛出以下错误:(_ value ...)
。
syntax: no pattern variables before ellipsis in template in: ...
我打算以与外部宏的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)"
答案 0 :(得分:7)
Alexis King的回答很好。然而,我觉得更容易思考的另一种方法是使用#:with
模式(或with-syntax
),将ooo
之类的内容定义为文字省略号。< / p>
您可以使用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 ...)]))
答案 1 :(得分:5)
要在语法模板中“转义”省略号,您可以使用语法(... <form>)
,其中<form>
是一种语法模板,其中...
序列按字面处理。因此,您可以包装一段语法以包含文字省略号:
> #'(... (syntax-rules ()
[(x ...) (list x ...)]))
#<syntax:4:9 (syntax-rules () ((x ...) (li...>
您可以使用它来包围内部宏定义以转义内部省略号:
(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 ...)]))
但是,这实际上并不完全正确,因为您的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 ...)]))
这应该按预期工作。