BOUNDP 检查 PROGV 中的自由变量?

zac*_*que 2 common-lisp

假设 和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

谢谢!

ign*_*ens 6

我认为标准中的措辞很糟糕,但其目的是

(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)

这意味着您可以避免有人可能以您无法控制的方式污染环境的问题。