在 Common Lisp 中随着堆栈展开修改条件

Amending a condition as the stack unwinds in Common Lisp

我正在编写一些 lisp 代码,这些代码会修改 CVS 存储库,以便使其成为 git 转换的形状。因此,当出现问题时,它可能不是我的代码中的错误,而是可能需要修复的输入数据不准确。

在我的代码的深处,我将拥有(比方说)一些通过取交集来合并两个日期范围的函数。如果那个交叉点结果是空的,我会报错。这一切都很好,但是我的 "merge dates" 函数缺少用户(我!)需要的很多信息,以便找出问题所在。例如,我正在处理哪个 CVS 主文件 ("foo,v")?我在想哪个分支?等等等等

我对这个问题的部分解决方案是处理并重新引发错误。比如这样的代码:

             (handler-case
                 (do-something)
               (unclear-graft-point (c)
                 (setf (slot-value c 'master) master)
                 (setf (slot-value c 'branch) branch)
                 (error c)))

它在重新引发错误之前设置了一些有用信息的额外插槽。

条件的报告函数然后检查是否已设置这些插槽,如果已设置,将使用它们提供更有帮助的错误消息。

不幸的是,我得到的回溯在顶级重新加注时停止。这是有道理的:这是我写的代码。但这并不是我想要的...

在 Common Lisp 中有没有一种方法可以 "annotate" 一个条件,因为它快速过去,而不重新提出它,因此,部分展开堆栈而不在回溯中报告它?

我提供了关于我正在做的事情的合理数量的背景信息,希望如果这不可能,有人会说 "Ah, what you should do in this situation is...":我只是以错误的方式做这件事吗?

是的,有一种适用于您的情况的 Common Lisp 技术 - 它称为 HANDLER-BIND. You can find a detailed explanation and use cases for it alongside other condition-handling machinery in Peter Seibel's Practical Common Lisp Chapter 19. Conditions and Restarts