使用语法列表作为函数的形式参数



这是场景:给定形式[sym ...]的模式(例如 [a b][a b c d] ( 我想生成(使用宏(函数,这些函数连接模式中的符号,但也将它们作为参数提供。例如,[a b]转换为以下形式的内容

(define (ab a b) 
  body)

在这篇文章中,有人通过一个名为 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以便我可以将其内容用作函数的形式参数,这与使用省略号兼容?

要直接回答您的问题,您可以将#'(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 ...)
                   ...))))))

最新更新