2

我正在尝试编写模式匹配宏。我还没有走多远,但我已经很困惑了。我的测试代码如下

#!r6rs

(import (for (rnrs base (6)) run expand)
        (for (rnrs syntax-case (6)) expand)
        (rnrs io simple (6)))

(define-syntax matcher
  (lambda (stx)

    (define (parse-clauses c)
      #'x)

    (syntax-case stx ()
      ((_ c ...)
       (with-syntax ((body (parse-clauses #'(c ...))))
         #'(lambda (x) body))))))

(write ((matcher) '(1 2 3))) (newline)

执行此操作会产生输出(1 2 3)

老实说,我写这段代码是因为它会失败。我认为从返回的语法parse-clauses是指未定义的符号x。但似乎#'x返回的parse-clauses确实引用x了 lambda 表达式中的参数。我不知道为什么。

这种细微的变化让我更加困惑。

#!r6rs

(import (for (rnrs base (6)) run expand)
        (for (rnrs syntax-case (6)) expand)
        (rnrs io simple (6)))

(define-syntax matcher
  (lambda (stx)

    (define (parse-clauses c)
      (let ((x 1))
        #'x))

    (syntax-case stx ()
      ((_ c ...)
       (with-syntax ((body (parse-clauses #'(c ...))))
         #'(lambda (x) body))))))

(write ((matcher) '(1 2 3))) (newline)

这会产生错误x: identifier used out of context in: x。我理解的这个错误x是在本地绑定的parse-clauses,但是我在该范围之外使用了引用,所以我得到了一个错误。

我想我要说的是第二个示例表明词法上下文很重要,但在第一个示例中没有词法绑定,x那么它为什么最终引用了不相关的绑定?

我希望这不会太混乱,欢迎任何解释。

我正在使用球拍 5.3.6。

4

1 回答 1

0

引用 lambda 参数,x因为它们都是由相同的宏扩展步骤引入的——宏系统仅区分由不同步骤引入的标识符(如果此宏扩展为另一个引入另一个的宏x,它将是不同的)。

我认为第二个错误是因为x被绑定为编译时变量(parse-clauses是编译时函数)并且它以某种方式干扰x了 lambda。

于 2013-11-23T11:53:48.820 回答