这是场景:给定[sym ...]
形式的模式(例如[a b]
和[a b c d]
)我想生成(使用宏)函数来连接模式中的符号,但也提供它们作为参数。例如,[a b]
转换为
(define (ab a b)
body)
在this post中,有人通过名为signal-list
的语法类帮助我生成函数的名称。在下面的代码中,我可以将signals
模式变量与(sig ...)
形式的模式匹配,然后我可以使用它来生成所需的函数定义。
(define-syntax (define-something stx)
(syntax-parse stx
[(_ (signals:signal-list body ...))
(syntax-parse #'signals
[(sig ...)
#'(define (signals.concatenated-ids sig ...)
body ...)])]))
与此宏匹配的示例:
(define-something
([a b] 'body))
扩展为(define (ab a b) 'body)
但是,如果我想生成多个函数定义,宏如何工作?例如:
(define-something
([a b] 'body)
([c d e] 'body))
=>
(begin (define (ab a b) 'body)
(define (cde c d e) 'body))
我可以在第一个语法分析的模式中添加省略号:
(_ (signals:signal-list body ...) ...)
但是我不能使用第二个语法分析来匹配signals
,因为它需要省略号。是否有一种不同的方法来“解构”signals
,以便我可以将其内容用作函数的形式参数,这与使用省略号兼容?
答案 0 :(得分:2)
要直接回答您的问题,您可以将#'(signals ...)
(代替现有的#'signals
)传递给内部syntax-parse
调用。
作为一个概念证明,我写了一个syntax-case
版本的宏(因为我还不知道syntax-parse
)。您应该能够轻松地将相同的技术适应syntax-parse
:
(define-syntax (define-something outerstx)
(define (make-name paramstx)
(datum->syntax outerstx
(string->symbol
(apply string-append
(map symbol->string (syntax->datum paramstx))))))
(define (make-names innerstx)
(syntax-case innerstx ()
(()
#'())
(((param ...) rest ...)
(with-syntax ((name (make-name #'(param ...)))
((next ...) (make-names #'(rest ...))))
#'(name next ...)))))
(syntax-case outerstx ()
((_ ((param ...) body ...)
...)
(with-syntax (((name ...) (make-names #'((param ...) ...))))
#'(define-values (name ...)
(values (lambda (param ...)
body ...)
...))))))