为什么 (let ((x 'huh?)) (cons (boundp 'x) x)) 的计算结果为 (NIL . HUH?)?
How come (let ((x 'huh?)) (cons (boundp 'x) x)) evaluates to (NIL . HUH?)?
我不明白这个:
CL-USER> (let ((x 'huh?)) (cons (boundp 'x) x))
(NIL . HUH?)
我曾预计在上面的 let
表达式中,x
会被绑定,因此整个表达式的计算结果会是 (t . huh?)
。否则,如果(与我的预期相反)x
没有绑定在 let
的主体中,那么至少上面表达式的评估会导致错误(由于我的已将未绑定变量作为第二个参数传递给 cons
).
让我更加困惑的是,Common Lisp HyperSpec 对 boundp
says 的描述:
Returns true if symbol is bound; otherwise, returns false.
...其中“绑定”一词超链接到此 glossary definition(我强调)1:
bound adj., v.t. 1. adj. having an associated denotation in a binding. ``The variables named by a let are bound within its body.'' See unbound. 2. adj. having a local binding which shadows[2] another. ``The variable print-escape is bound while in the princ function.'' 3. v.t. the past tense of bind.
此外,let
的 CLHS 文档说了以下内容(我的重点):
...all of the variables varj are bound to the corresponding values; ...
当然,boundp
的 HyperSpec 页面(我之前已经链接到它)也有以下示例:
(let ((x 2)) (boundp 'x)) => false
...这确实可以证明我所观察到的实际上是“官方记录的行为”这一断言,但鉴于我在上面引用的所有其他内容,这种狭隘正确的理由并不能让人感到安慰。
有人可以为我解决这个巨大的(并且希望只是表面上的)矛盾吗?
1 我意识到上面突出显示的短语只是“绑定”一词在句子中的用法示例,但它会一个真正反常的例子,如果它所说的与 Common Lisp 的实际情况完全相反。
boundp
用于判断符号是否绑定在全局环境中。请注意以下来自 HyperSpec 的两个示例:
(let ((x 2)) (boundp 'x)) ;=> false
(let ((x 2)) (declare (special x)) (boundp 'x)) ;=> true
页面底部的注释说:
The function bound
determines only whether a symbol has a value in the global environment; any lexical bindings are ignored.
注释中 bound
而不是 boundp
的出现似乎是错字。无论如何,CLTL2 对此更具体一些:
boundp
is true if the dynamic (special) variable named by symbol has a value; otherwise, it returns nil
.
注意 fboundp
也有类似的限制;这是来自 HyperSpec:
的示例
(flet ((my-function (x) x))
(fboundp 'my-function)) ;=> false
boundp
处理词法变量没有多大意义。来自 HyperSpec 3.1.2.1.1.1 Lexical Variables:
A lexical variable always has a value. There is no operator that introduces a binding for a lexical variable without giving it an initial value, nor is there any operator that can make a lexical variable be unbound.
这就是说词法变量总是绑定在它们的词法环境中。但是动态变量 可能 是 bound or unbound 之一,两者中的哪一个取决于提问的环境:
The value part of the binding for a dynamic variable might be empty; in this case, the dynamic variable is said to have no value, or to be unbound. A dynamic variable can be made unbound by using makunbound
....
A dynamic variable is unbound unless and until explicitly assigned a value, except for those variables whose initial value is defined in this specification or by an implementation.
这可能有点令人困惑,但是 BOUNDP
的规范确实是这样说的:
The function bound [sic (it should be boundp)] determines only whether a symbol has a value in the global environment; any lexical bindings are ignored.
因此它只会通知您给定符号是否已绑定到全局环境中,如果变量的值单元格设置为某个值(请参阅 SYMBOL-VALUE
),就会发生这种情况,
或者变量被声明为 special 并且之前被 let
形式绑定。第二种情况尤其发生在用 defvar
和 defparameter
声明的变量上,但也发生在你声明为特殊的任何变量上:
(let ((%my-var% 0))
(declare (special %my-var%))
...)
请注意,每次您想使用 %my-var%
时,您都需要使用该声明,除非您在全局声明它。
(defun use-my-var (input)
(declare (special %my-var%))
(print `(:my-var ,%my-var% :input ,input)))
当您编写 use-my-var
函数时,您通常可以毫无问题地识别 input
已绑定,事实上,如果不是这种情况,编译器会警告您。对于词法作用域,(boundp x)
将编译为常量值 T 或 NIL。检查符号的 symbol-value
是全局绑定还是动态绑定更有趣。
这里,由于%my-var%
是一个特殊的变量,所以在不同的调用上下文中可以绑定也可以不绑定:
(let ((%my-var% 0))
(declare (special %my-var%))
(use-my-var 1))
=> (:my-var 0 :input 1)
(use-my-var 0)
;; ERROR: The variable %MY-VAR% is unbound.
我不明白这个:
CL-USER> (let ((x 'huh?)) (cons (boundp 'x) x))
(NIL . HUH?)
我曾预计在上面的 let
表达式中,x
会被绑定,因此整个表达式的计算结果会是 (t . huh?)
。否则,如果(与我的预期相反)x
没有绑定在 let
的主体中,那么至少上面表达式的评估会导致错误(由于我的已将未绑定变量作为第二个参数传递给 cons
).
让我更加困惑的是,Common Lisp HyperSpec 对 boundp
says 的描述:
Returns true if symbol is bound; otherwise, returns false.
...其中“绑定”一词超链接到此 glossary definition(我强调)1:
bound adj., v.t. 1. adj. having an associated denotation in a binding. ``The variables named by a let are bound within its body.'' See unbound. 2. adj. having a local binding which shadows[2] another. ``The variable print-escape is bound while in the princ function.'' 3. v.t. the past tense of bind.
此外,let
的 CLHS 文档说了以下内容(我的重点):
...all of the variables varj are bound to the corresponding values; ...
当然,boundp
的 HyperSpec 页面(我之前已经链接到它)也有以下示例:
(let ((x 2)) (boundp 'x)) => false
...这确实可以证明我所观察到的实际上是“官方记录的行为”这一断言,但鉴于我在上面引用的所有其他内容,这种狭隘正确的理由并不能让人感到安慰。
有人可以为我解决这个巨大的(并且希望只是表面上的)矛盾吗?
1 我意识到上面突出显示的短语只是“绑定”一词在句子中的用法示例,但它会一个真正反常的例子,如果它所说的与 Common Lisp 的实际情况完全相反。
boundp
用于判断符号是否绑定在全局环境中。请注意以下来自 HyperSpec 的两个示例:
(let ((x 2)) (boundp 'x)) ;=> false
(let ((x 2)) (declare (special x)) (boundp 'x)) ;=> true
页面底部的注释说:
The function
bound
determines only whether a symbol has a value in the global environment; any lexical bindings are ignored.
注释中 bound
而不是 boundp
的出现似乎是错字。无论如何,CLTL2 对此更具体一些:
boundp
is true if the dynamic (special) variable named by symbol has a value; otherwise, it returnsnil
.
注意 fboundp
也有类似的限制;这是来自 HyperSpec:
(flet ((my-function (x) x))
(fboundp 'my-function)) ;=> false
boundp
处理词法变量没有多大意义。来自 HyperSpec 3.1.2.1.1.1 Lexical Variables:
A lexical variable always has a value. There is no operator that introduces a binding for a lexical variable without giving it an initial value, nor is there any operator that can make a lexical variable be unbound.
这就是说词法变量总是绑定在它们的词法环境中。但是动态变量 可能 是 bound or unbound 之一,两者中的哪一个取决于提问的环境:
The value part of the binding for a dynamic variable might be empty; in this case, the dynamic variable is said to have no value, or to be unbound. A dynamic variable can be made unbound by using
makunbound
....
A dynamic variable is unbound unless and until explicitly assigned a value, except for those variables whose initial value is defined in this specification or by an implementation.
这可能有点令人困惑,但是 BOUNDP
的规范确实是这样说的:
The function bound [sic (it should be boundp)] determines only whether a symbol has a value in the global environment; any lexical bindings are ignored.
因此它只会通知您给定符号是否已绑定到全局环境中,如果变量的值单元格设置为某个值(请参阅 SYMBOL-VALUE
),就会发生这种情况,
或者变量被声明为 special 并且之前被 let
形式绑定。第二种情况尤其发生在用 defvar
和 defparameter
声明的变量上,但也发生在你声明为特殊的任何变量上:
(let ((%my-var% 0))
(declare (special %my-var%))
...)
请注意,每次您想使用 %my-var%
时,您都需要使用该声明,除非您在全局声明它。
(defun use-my-var (input)
(declare (special %my-var%))
(print `(:my-var ,%my-var% :input ,input)))
当您编写 use-my-var
函数时,您通常可以毫无问题地识别 input
已绑定,事实上,如果不是这种情况,编译器会警告您。对于词法作用域,(boundp x)
将编译为常量值 T 或 NIL。检查符号的 symbol-value
是全局绑定还是动态绑定更有趣。
这里,由于%my-var%
是一个特殊的变量,所以在不同的调用上下文中可以绑定也可以不绑定:
(let ((%my-var% 0))
(declare (special %my-var%))
(use-my-var 1))
=> (:my-var 0 :input 1)
(use-my-var 0)
;; ERROR: The variable %MY-VAR% is unbound.