Common Lisp中的动态非本地出口

Tia*_*ong 3 dynamic common-lisp exit

根据Common Lisp the Language动态非本地退出部分,第2版,

一旦启动控制权转移,就会放弃干预出口; 在抛出的情况下,这发生在实施说明中提到的"第二次通过"的开始.尝试将控制权转移到动态范围已结束的出口是错误的.

1.3.4但是在SBCL 中:

(catch 'a
  (catch 'b
    (unwind-protect
         (throw 'a "returning from protected")
      (throw 'b "returning from unwind"))))
;; => "returning from unwind"
Run Code Online (Sandbox Code Playgroud)

这似乎不正确.'b在执行受保护和清理表格之间是否应该解除退出点,从而使上述违法?同一页上的划船示例表明了相同的情况.

相反,SBCL的行为似乎与替代提案相对应:

...放弃退出应该与unwind-protect清理条款的评估以及动态绑定和捕获标记的撤消混为一谈,以相反的顺序执行所有操作.

这只是CLtL2与最终规格不同的问题吗?

cor*_*ump 5

正如jkiiski所解释的那样,ANSI Common Lisp中的行为未定义.UNWIND-PROTECTCLHS部分引用了这个例子:

;;; 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))))
Run Code Online (Sandbox Code Playgroud)