如何将“rest”变量绑定到Scheme中宏的值列表中

时间:2010-01-12 18:26:48

标签: macros scheme racket

我想创建一个帮助宏来编写匹配扩展。我有这样的事情:

(define-match-expander my-expander
  (λ (stx)
    (let* ([dat (cdr (syntax-e stx))]
           [var1 (car dat))]
           [var2 (cadr dat)])
      ;transformer goes here )))

所以我想要一个允许绑定的宏。我从这样的事情开始:

(define-syntax-rule (define-my-expander (id vars ...) body)
  (define-match-expander id
    (λ (stx)
      (match-let ([(vars ...) (cdr (syntax-e stx))])
        body))))

match-let未在转换时定义。

第一个问题是有没有其他方法这样做(制作这个扩展器,我的意思)?也许在plt-scheme中已经有类似的东西,我不知道,或者我在某种程度上做错了。

无论第一个问题的答案如何,如果我想将变量列表绑定到宏内的值列表,我应该怎么做?

编辑:结合Eli的答案宏,现在看起来像这样:

(define-syntax-rule (define-my-expander (id vars ...) body)
  (define-match-expander id
    (λ (stx)
      (syntax-case stx ()
        [(_ vars ...)
         body]))))

1 个答案:

答案 0 :(得分:4)

我不知道你想要达到的是什么,但我的猜测是朝着正确的方向前进:

(define-match-expander my-expander
  (lambda (stx)
    (syntax-case stx ()
      [(_ (var1 var2) stuff ...)
       ;; use #'var1 #'var2 and #'(stuff ...) here
       ])))

问题在于,syntax-e用于“解包”一个语法对象,并为您提供它所拥有的内容 - 但实际内容可能会让您感到惊讶。例如,(foo . (bar))的内容与(foo bar)的内容略有不同。所以一般来说,使用syntax-case为您进行模式匹配更容易 。除了更容易之外,它还会在出现错误时提供一些明智的错误消息,而不是您的代码所带来的错误消息。