假设 和a都未b绑定(即(notany #'boundp '(a b))=> T),那么这将按预期工作:
(progv '(a b) '(1)
(boundp 'a)) ; => T
Run Code Online (Sandbox Code Playgroud)
然后PROGV进入 CLHS 状态:
如果提供的值太少,则剩余的符号将被绑定,然后变得没有值。
这与我在 REPL 中看到的相矛盾:
(progv '(a b) '(1)
(boundp 'b)) ; => NIL
Run Code Online (Sandbox Code Playgroud)
我期待(boundp 'b)着回来T。
问:我是否误解了 CLHS 中的措辞?或者这是 SBCL 中的一个错误?
环境:SBCL 2.2.10,Linux x86_64
谢谢!
我认为标准中的措辞很糟糕,但其目的是
(progv '(a b) '(1) ...)
Run Code Online (Sandbox Code Playgroud)
相当于
(progv '(a b) '(1 nil)
(makunbound 'b)
...)
Run Code Online (Sandbox Code Playgroud)
这与根本不绑定有很大不同,b正如您通过考虑以下内容所看到的:
(progv '(b) '(3)
(progv '(b) '()
... b unbound here ...)
(symbol-value 'b))
Run Code Online (Sandbox Code Playgroud)
其评估结果为3. 问题在于makunbound删除了当前范围内符号的动态绑定值。在浅层绑定实现中,这与简单地将符号的值单元标记为没有值是一样的,因为外部值将在适当的时候恢复。但在深度绑定实现中,绑定必须仍然存在于绑定堆栈中,但其值必须以某种方式标记为“未绑定”。
也许问题实际上在于,boundp至少可以说makunbound是错误命名的:boundp真正告诉您符号的当前动态绑定是否有值,而不是根本不存在值,并makunbound从当前动态绑定中删除该值。但这些名字都被CL继承了。没有办法告诉(并且可能应该没有办法)是否存在符号的当前非全局动态绑定。
最后,这种行为progv很有用,因为它意味着你可以说
(progv '(a b c) '()
... now I know a, b, c are unbound ...)
Run Code Online (Sandbox Code Playgroud)
这意味着您可以避免有人可能以您无法控制的方式污染环境的问题。