(我们在这里谈论的是 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/3C
调用的论点统一
— 。
system_error
要了解系统错误是什么,我们需要查看 7.12.2 j 小节:
j) 在执行的任何阶段都可能出现系统错误
。应有
系统错误的条件以及处理器在系统错误后采取的行动
取决于实现。它有
形式system_error
。
因此,处理器在系统错误后采取的行动取决于实现。无限循环也可以。
在符合标准的程序中,您不能依赖这种情况下的任何特定操作。
广告注释 1:注释不是规范性的。见 1.1 注释。它本质上是一个总结。
广告注释 2:这是为了避免任何过度规范。这些部分在标准中尽可能保持模糊,因为系统错误可能损坏了 Prolog 系统。这与资源错误非常相似。理想情况下,系统会捕获它们并继续执行,但在一般情况下,许多实现很难保证这一点。
广告注释 3:形式语义本质上是另一种实现。在某些部分,实现必须做出某些决定,而规范可以保留所有可能性。除此之外,请注意形式语义不是规范的。不过,它确实有助于调试标准。
编辑:在你说的评论中:
(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 的范围。报告这样的错误并继续执行可能很有意义。
目的
这里的另一点是技术标准的实际用途。技术标准经常被误解为完全保证系统将“正常”工作。但是,如果系统符合技术标准,这并不意味着它适合任何目的或用途。为了向您展示非常极端的情况,请考虑exit 1
可能被认为是符合 13211-1 的处理器的 shell 命令(前提是它随附定义所有实现定义的功能的文档)。为什么?好吧,当系统启动时,它可能会意识到未满足最低要求(1 Scope,Note b),因此它会产生系统错误,通过产生错误代码 1 来处理。
您真正想要的是一个确实符合并适合某些目的的系统(超出 13211-1 的范围)。因此,除了问自己某个行为是否符合要求之外,您还将了解该系统如何适用于某些目的。
一个很好的例子就是资源错误。许多 Prolog 系统能够处理某些资源错误。考虑:
p(-X) :- p(X).
并且查询catch(p(X),error(E,_),true).
A 系统现在有几个机会:无限循环(这需要非常非常智能的 GC),成功E = resource_error(Resource)
,成功E = system_error
,停止执行,出现一些错误代码,耗尽所有资源。
虽然没有声明系统必须捕获此类错误,但标准中提供了所有机制来执行此操作。
同样在 a 的情况下system_error
:如果有意义,在 Prolog 中正确报告系统错误可能是一个好主意,但是,如果事情走得太远,安全救助仍然不是可能发生的最坏情况。事实上,最糟糕(但仍然符合标准)的方法是继续执行“好像”一切都很好,而实际上并非如此。