词汇范围和语法案例

时间:2013-11-23 10:39:02

标签: scheme r6rs

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

#!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确实引用了lambda表达式中的参数x。我不知道为什么。

这种微小的变化使我更加困惑。

#!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。我理解这个错误,xparse-clauses本地绑定,但我在该范围之外使用引用,所以我收到错误。

我想我所说的是第二个例子表明词汇上下文很重要,但在第一个例子中,x没有词法绑定,那么它最终如何引用一个不相关的绑定呢? / p>

我希望不要太困惑,欢迎任何解释。

我正在使用Racket 5.3.6。

1 个答案:

答案 0 :(得分:0)

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

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