(我们在这里讨论的是 ISO/IEC 13211-1:1995)
控制结构throw/1 (7.8.10) 的定义在两个地方指出,在这种情况下会出现系统错误。首先,正如您所观察到的,有 7.8.10.1 c:
c) 如果 S 现在是系统错误 (7.12.2 j)
空,
然后是错误子句:
7.8.10.3 错误
a) B 是一个变量
— instantiation_error.
b) B 不与 catch/3 的任何调用
的 C 参数统一
——system_error.
要了解系统错误是什么,我们需要查看子条款 7.12.2 j:
j)
执行的任何阶段都可能出现系统错误。这
应有一个
系统错误的条件,以及
处理器在
系统错误后采取的行动是
实现依赖。它的格式为
system_error。
因此,处理器在系统错误后采取的操作取决于实现。无限循环也可以。
在符合标准的程序中,在这种情况下您不能依赖任何特定操作。
广告注释 1:注释不是规范性的。见 1.1 注释。它本质上是一个总结。
广告说明 2:这是为了避免过度指定。这些部分在标准中尽可能保持模糊,因为系统错误可能损坏了 Prolog 系统。这与资源错误非常相似。理想情况下,系统会捕获它们并继续执行,但在一般情况下,许多实现很难保证这一点。
注意事项 3:形式语义本质上是另一种实现。在某些部分,实现必须做出某些决定,而规范可以保留所有可能性。除此之外,请注意形式语义不是规范的。不过,它确实有助于调试标准。
编辑:在 cmets 你说:
(1mo) 所以你是说这允许处理器在系统错误发生时立即执行其实现相关的操作——不仅仅是在它未被捕获之后? (2do) 从而免除了在 7.12.1 中应用目标转换的必要性? (3tio) 如果系统错误根本无法捕获(通过 catch/3)也可以吗?
1 个月
7.12.2 j中的句子
...处理器在系统错误后采取的行动取决于实现。
有效地推翻了 7.12.1。类似于 7.12.2 h,它也可能发生在“执行的任何阶段”。
为了确保我们正确阅读法典,暂时假设相反。想象一下发生了系统错误,而 7.12.1 现在会产生这样一个在任何地方都没有发现的错误,然后我们又会遇到系统错误等。因此:上面的句子永远不会适用。仅这一点就表明我们在这里读错了一些东西。
另一方面,想象一下当系统完全损坏时发生系统错误的情况。现在应该如何执行 7.12.1 呢?所以 Prolog 系统将无法执行这个循环。这是否意味着 Prolog 处理器只有在我们能够证明永远不会出现系统错误的情况下才能符合要求?这实际上是不可能的,尤其是因为
7.12.2 错误分类
注意事项
...
4 可能会发生系统错误,例如 (a) 在与
操作系统(例如,磁盘崩溃或中断),
...
实际上这意味着不可能有任何符合 Prolog 的处理器。
2做
7.12.1 描述了在 Prolog 中处理错误的方式。也就是说,如果您能够在 Prolog 中处理错误,那么 Prolog 系统应该使用这种方法。但是,在某些情况下,处理 Prolog 中的错误可能非常困难甚至不可能(参见上面的案例)。在这种情况下,系统可能会退出。
3tio
简短的回答:是的。这是一个非常极端但有效的读法,即系统错误是不可捕获的,然后执行将被终止。但也许,先退一步了解 (a) 技术标准的用途和用途,(b) 标准的范围。
范围
或者,不如从 b 开始:在 1 Scope 中,我们有:
注意 - ISO/IEC 13211 的这一部分未指定:
...
f) 用户环境(顶层循环、调试器、库
Prolog 处理器的系统、编辑器、编译器等)。
(严格来说,这只是一个注释,但如果您仔细阅读该标准,您会发现这些方面并没有具体说明。)我有点怀疑您真正想要的是了解顶层循环应该如何处理未捕获的错误。但是,这个问题超出了 13211-1 的范围。报告这样的错误并继续执行可能很有意义。
目的
这里的另一点是技术标准的实际用途。技术标准经常被误解为完全保证系统将“正常”工作。但是,如果系统符合技术标准,这并不意味着它适合任何目的或用途。为了向您展示非常极端的情况,请考虑 shell 命令exit 1,它可能被认为是符合 13211-1 的处理器(前提是它随附定义所有实现定义的功能的文档)。为什么?好吧,当系统启动时,它可能会意识到没有满足最低要求(1 Scope,Note b),因此它会产生一个系统错误,通过产生错误代码 1 来处理。
您真正想要的是一个确实符合并且的系统适合某些目的(超出 13211-1 的范围)。因此,除了问自己某个行为是否符合要求之外,您还将了解该系统是否适合某些目的。
资源错误就是一个很好的例子。许多 Prolog 系统能够处理某些资源错误。考虑:
p(-X) :- p(X).
和查询catch(p(X),error(E,_),true). 一个系统现在有几个机会:无限循环(这需要非常非常智能的 GC),以E = resource_error(Resource) 成功,以E = system_error 成功,以一些错误代码停止执行,吃掉所有资源。
虽然没有声明系统必须捕获此类错误,但标准中提供了所有机制来执行此操作。
system_error 的情况类似:如果有意义,在 Prolog 中正确报告系统错误可能是个好主意,但是,如果事情走得太远,安全救援仍然不是最坏的情况发生。事实上,最糟糕(但仍然符合要求)的方法是继续执行“好像”一切都很好,但实际上并非如此。