【问题标题】:throw without catch in ISO Prolog在 ISO Prolog 中不接不接投掷
【发布时间】:2014-08-04 18:12:13
【问题描述】:

在 ISO Prolog 中没有合适的 catch/3 的情况下,我正在为 throw/1 的精确语义而苦苦挣扎。我正在阅读 ISO Prolog 规范,在我看来,执行将以无限递归结束。

(请注意,您必须有权访问 ISO Prolog 标准才能解释此问题)。

第 1 步。假设我们调用 throw(unknown),但堆栈上没有任何 catch/3。

第 2 步。它将在 7.8.10.1 c) 中结束,说这将是系统错误 (7.12.2 j)。

第 3 步。这是在其他地方用于其他地方的相同类型的表述,所以我认为它应该以相同的方式解释。因此 7.12.1 适用,当前目标 (throw/1) 将替换为 throw(error(system_error, Imp_def))。

第 4 步。执行此目标将在堆栈上找不到它的活动“捕获”。因此它应该尝试相同的步骤,在第 2 步继续,依此类推 => 无限递归。

您可能会说,将未捕获的“抛出”转换为 system_error 是“最终的”,并且不像其他错误那样需要进一步处理,为了避免我描述的问题,它可能必须如此,但我的问题是,标准在哪里涵盖了这一点?

为了完整起见,还有一些其他说明:

  1. 7.12.2 中的注释 4 还提到了在这些情况下可能出现系统错误。我认为那里使用的公式(“....没有主动目标 catch/3”)在另一个方面引入了一些混淆,因为它应该符合条件,即捕手必须与错误术语(B )。

  2. 将未捕获的 throw-s 转换为系统错误背后的想法是什么?看起来它的存在可能是为了让顶级 Prolog 处理器的生活“更轻松”,以便它只接收一种可预测的错误?对我来说,这带来的问题多于好处 - 错误的真正原因将因此消失 - 任何意见或评论?

  3. 形式语义(附件 A)似乎也以某种方式与之抗争,尽管我没有详细研究它。在 A.2.5 中,它提到“......但是在正式规范中,在根部有一个捕手......”,并将其与例如 findall/3 的执行相关联。所以这里的正式规范与正文不同?

【问题讨论】:

    标签: iso-prolog


    【解决方案1】:

    (我们在这里讨论的是 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 中正确报告系统错误可能是个好主意,但是,如果事情走得太远,安全救援仍然不是最坏的情况发生。事实上,最糟糕(但仍然符合要求)的方法是继续执行“好像”一切都很好,但实际上并非如此。

    【讨论】:

    • 我接受这个作为答案;尽管它并没有完全解决我所有的担忧(见下文)。我的意思不是挑剔标准文本,而是我需要一些对标准非常有经验的人确认我的理解是正确的,我已经收到了 - 谢谢。
    • 我仍然有保留的部分如下:我实际上认为标准中真正暗示了无限循环,而不是“可能性”——尽管人们(包括你和我)倾向于不要将文本解释为逐字逐句的细节。我可以仅根据规范部分提出该主张,而将注释和附件 A 放在一边。推理如下: 7.8.10.3 b) 使用与其他任何地方相同的公式,即不告诉 THIS system_error 是“最终的”。在 7.12.2 j 中相同 - 与其他错误没有区别。因此应用 7.12.1 是必要的,不是吗?
    • 在对此进一步摸不着头脑之后,我想我现在明白你特别想指出我在 7.12.2 j 中的部分,它说“......处理器在系统错误取决于实现。”。所以你说这允许处理器在发生系统错误时立即执行其实现相关的操作 - 不仅仅是在它未被捕获之后?从而减轻它在 7.12.1 中应用目标转换的必要性?如果系统错误根本无法捕获(通过 catch/3)也可以吗?
    • 这绝对是一个很棒的答案,完全可以让我继续前进。我的主要误解是在阅读标准时,例如 7.12.1 必须始终适用。混淆的另一个来源是 7.8.10.3 b),我认为这是一种“技巧”,它允许标准避免引入一个单独的概念,即如何从作为主题的 Prolog 部分传递未捕获的错误的标准。
    猜你喜欢
    • 2011-03-13
    • 2017-10-12
    • 2016-05-11
    • 1970-01-01
    • 1970-01-01
    • 2016-07-02
    • 2020-01-05
    • 1970-01-01
    • 2019-04-27
    相关资源
    最近更新 更多