为什么 x 没有绑定在 (define lambda (lambda (x) x)) 中?
Why is x not bound in (define lambda (lambda (x) x))?
我试图评估这个:(define lambda (lambda (x) x))
。 MIT Scheme 11.2 报错:;Unbound variable: x
。 Chez Scheme 9.5 也报错:Exception: variable x is not bound
。为什么 x
没有绑定?我认为 define
会将 (lambda (x) x)
评估为匿名函数,然后将 lambda
定义为该匿名函数。 x
涉及到哪里?
我在 Racket 7.2 和 Guile 3.0.1 中没有收到任何错误。
这不是有效的方案代码:
(define lambda (lambda (x) x))
R7RS 在第 5.4 节关于语法定义的内容中似乎很清楚禁止这样做:
However, it is an error for a definition to define an identifier whose binding has to be known in order to determine the meaning of the definition itself, or of any preceding definition that belongs to the same group of internal definitions.
在发布的代码中,标识符 lambda
被重新定义,但必须知道 lambda
本身的绑定才能确定新定义的含义;上面的语言禁止这样做。
R6RS 在 Chapter 10 中有一些关于扩展过程的类似语言,但 R6RS 语言与扩展过程的技术细节耦合得更紧密。我漂亮确定它以同样的方式适用于这种情况,但不是 100% 确定。
A definition in the sequence of forms must not define any identifier whose binding is used to determine the meaning of the undeferred portions of the definition or any definition that precedes it in the sequence of forms.
OP 注意到错误消息 Exception: variable x is not bound
并询问:“x 涉及何处?”
假设 (define lambda (lambda (x) x))
格式不正确,因此不是有效的 Scheme,尝试解释此类行为也 没有意义。然而,似乎可以通过尝试以类似方式重新定义其他句法关键字来触发这种行为。考虑:
> (define if (if x y z))
Exception: variable z is not bound
这里好像很明显z
是未绑定的,所以这个错误看起来也不是没有道理的。但是现在:
> (define if (if #t 1 2))
Exception: variable if is not bound
甚至 if
在 define
形式的右侧表达式中也是未绑定的!如果我们假设 (define lambda (lambda (x) x))
中发生了类似的事情,那么 lambda
在右边的表达式中是未绑定的,如果是这种情况,那么 (lambda (x) x)
不是 评估为特殊形式,但作为普通过程调用。过程调用中参数的求值顺序未指定,因此在这种情况下 x
可以在 lambda
之前报告为未绑定是完全合理的。我们可以去掉未绑定的 x
s 的外观,看看 lambda
是否被绑定:
> (define lambda (lambda))
Exception: variable lambda is not bound
> (define lambda lambda)
Exception: variable lambda is not bound
所以这里的问题似乎是,尝试使用依赖于该关键字的含义的表达式重新定义语法关键字可能会导致语法关键字的绑定变得不可访问。
无论如何,请对最后一点持保留态度,因为最终这种重新定义不是有效代码,不应期望它有任何特定行为。
我试图评估这个:(define lambda (lambda (x) x))
。 MIT Scheme 11.2 报错:;Unbound variable: x
。 Chez Scheme 9.5 也报错:Exception: variable x is not bound
。为什么 x
没有绑定?我认为 define
会将 (lambda (x) x)
评估为匿名函数,然后将 lambda
定义为该匿名函数。 x
涉及到哪里?
我在 Racket 7.2 和 Guile 3.0.1 中没有收到任何错误。
这不是有效的方案代码:
(define lambda (lambda (x) x))
R7RS 在第 5.4 节关于语法定义的内容中似乎很清楚禁止这样做:
However, it is an error for a definition to define an identifier whose binding has to be known in order to determine the meaning of the definition itself, or of any preceding definition that belongs to the same group of internal definitions.
在发布的代码中,标识符 lambda
被重新定义,但必须知道 lambda
本身的绑定才能确定新定义的含义;上面的语言禁止这样做。
R6RS 在 Chapter 10 中有一些关于扩展过程的类似语言,但 R6RS 语言与扩展过程的技术细节耦合得更紧密。我漂亮确定它以同样的方式适用于这种情况,但不是 100% 确定。
A definition in the sequence of forms must not define any identifier whose binding is used to determine the meaning of the undeferred portions of the definition or any definition that precedes it in the sequence of forms.
OP 注意到错误消息 Exception: variable x is not bound
并询问:“x 涉及何处?”
假设 (define lambda (lambda (x) x))
格式不正确,因此不是有效的 Scheme,尝试解释此类行为也 没有意义。然而,似乎可以通过尝试以类似方式重新定义其他句法关键字来触发这种行为。考虑:
> (define if (if x y z))
Exception: variable z is not bound
这里好像很明显z
是未绑定的,所以这个错误看起来也不是没有道理的。但是现在:
> (define if (if #t 1 2))
Exception: variable if is not bound
甚至 if
在 define
形式的右侧表达式中也是未绑定的!如果我们假设 (define lambda (lambda (x) x))
中发生了类似的事情,那么 lambda
在右边的表达式中是未绑定的,如果是这种情况,那么 (lambda (x) x)
不是 评估为特殊形式,但作为普通过程调用。过程调用中参数的求值顺序未指定,因此在这种情况下 x
可以在 lambda
之前报告为未绑定是完全合理的。我们可以去掉未绑定的 x
s 的外观,看看 lambda
是否被绑定:
> (define lambda (lambda))
Exception: variable lambda is not bound
> (define lambda lambda)
Exception: variable lambda is not bound
所以这里的问题似乎是,尝试使用依赖于该关键字的含义的表达式重新定义语法关键字可能会导致语法关键字的绑定变得不可访问。
无论如何,请对最后一点持保留态度,因为最终这种重新定义不是有效代码,不应期望它有任何特定行为。