Common Lisp 中的动态非本地退出
Dynamic non-local exits in Common Lisp
根据 Common Lisp the Language,第 2 版 的 Dynamic Non-Local Exits 部分,
Intervening exits are abandoned as soon as the transfer of control is initiated; in the case of a throw, this occurs at the beginning of the "second pass" mentioned in the implementation note. It is an error to attempt a transfer of control to an exit whose dynamic extent has ended.
在 SBCL 1.3.4
中,但是:
(catch 'a
(catch 'b
(unwind-protect
(throw 'a "returning from protected")
(throw 'b "returning from unwind"))))
;; => "returning from unwind"
这似乎不正确。不应该在执行受保护和清理表单之间取消退出点 'b
,从而使上述行为非法吗?同一页上的划船示例表明了相同的情况。
SBCL 的行为似乎与替代提案相对应:
...the abandoning of exits should be lumped in with the evaluation of unwind-protect
cleanup clauses and the undoing of dynamic bindings and catch tags, performing all in reverse order of establishment.
这只是 CLtL2 与最终规格不同的问题吗?
正如 jkiiski 所解释的,该行为在 ANSI Common Lisp 中未定义。该示例在 CLHS 的 UNWIND-PROTECT
部分中引用:
;;; The following has undefined consequences because the catch of B is
;;; passed over by the first THROW, hence portable programs must assume
;;; its dynamic extent is terminated. The binding of the catch tag is not
;;; yet disestablished and therefore it is the target of the second throw.
(catch 'a
(catch 'b
(unwind-protect (throw 'a 1)
(throw 'b 2))))
根据 Common Lisp the Language,第 2 版 的 Dynamic Non-Local Exits 部分,
Intervening exits are abandoned as soon as the transfer of control is initiated; in the case of a throw, this occurs at the beginning of the "second pass" mentioned in the implementation note. It is an error to attempt a transfer of control to an exit whose dynamic extent has ended.
在 SBCL 1.3.4
中,但是:
(catch 'a
(catch 'b
(unwind-protect
(throw 'a "returning from protected")
(throw 'b "returning from unwind"))))
;; => "returning from unwind"
这似乎不正确。不应该在执行受保护和清理表单之间取消退出点 'b
,从而使上述行为非法吗?同一页上的划船示例表明了相同的情况。
SBCL 的行为似乎与替代提案相对应:
...the abandoning of exits should be lumped in with the evaluation of
unwind-protect
cleanup clauses and the undoing of dynamic bindings and catch tags, performing all in reverse order of establishment.
这只是 CLtL2 与最终规格不同的问题吗?
正如 jkiiski 所解释的,该行为在 ANSI Common Lisp 中未定义。该示例在 CLHS 的 UNWIND-PROTECT
部分中引用:
;;; The following has undefined consequences because the catch of B is
;;; passed over by the first THROW, hence portable programs must assume
;;; its dynamic extent is terminated. The binding of the catch tag is not
;;; yet disestablished and therefore it is the target of the second throw.
(catch 'a
(catch 'b
(unwind-protect (throw 'a 1)
(throw 'b 2))))