prolog - 关于解决意外 "Undefined procedure"错误的方法

标签 prolog

注意:需要明确的是,我提出以下问题的动机是学习 Prolog 和 SWI-Prolog 的方法,而不是为了忽略特定的错误消息。事实上,我已经知道一种方法来克服这个错误。我的问题是询问是否还有其他几种替代方案。

<小时/>

我的 Prolog 教科书中的一个练习要求人们描述从多个查询中应该期望的结果,假设人们事先查阅了以下知识库:

x(a).
z(b).
z(c).
z(d).
w(V) :- x(V).
w(V) :- y(V).
w(V) :- z(V).

至少在 SWI-Prolog 上,大多数查询都会失败,因为 SWI-Prolog 解释 y未定义。

从书末的习题解答可以看出,这不是作者想要的结果。也许有一个 Prolog 实现,练习将在解决方案呈现时转向。

尽管如此,我还是想了解解决该问题的好方法。

例如,考虑查询 w(x). 。该书的解决方案声称查询 w(x).应评估为 false. 。事实上,事情是这样的:

?- w(x).
ERROR: w/1: Undefined procedure: y/1
   Exception: (7) y(x) ? 

(此时,SWI-Prolog 期望我输入一些字母来指示如何响应异常。稍后会详细介绍。)

我正在寻找将上面的交互转变为的方法

?- w(x).
false.

?- 

...或者至少对于合适的 <ONE-LETTER RESPONSE>我可以给SWI-Prolog,以便它得出结论false 。 IOW,这样

?- w(x).
ERROR: w/1: Undefined procedure: y/1
   Exception: (7) y(x) ? <ONE-LETTER RESPONSE>
false.

?- 

我知道我的问题至少有一个答案,即简单地删除或注释掉该行:

w(V) :- y(V).

我想知道其他可能的解决方案,例如我之前提到的“合适的”。

另一种可能性是某些 SWI-Prolog 全局配置,这将导致上述交互更改为

?- w(x).
false.

?- 

第三种可能性是“定义”y以某种最小的方式。我能想到的唯一方法就是添加事实

y(dummy).

到知识库。有没有更简单的方法来定义 y ,不需要在讨论域中引入无关常量的一个?

最佳答案

(这并非特定于 SWI)

早在 20 世纪 70 年代的第一个 Prolog 系统实际上就按照您所描述的方式运行。很快我们就发现这是一个常见的错误来源。简单的拼写错误很长时间都没有被发现。当前的实现会产生一个干净的存在错误。这是自 1995 年以来的标准行为。

但是,您可以使用 ISO Prolog 标志 unknown 回到旧时代,它具有三个值 error (默认)、fail警告

?- inex.
ERROR: Undefined procedure: inex/0 (DWIM could not correct goal)
?- set_prolog_flag(unknown, fail).
Warning: Using a non-error value for unknown in the global module
Warning: causes most of the development environment to stop working.
Warning: Please use :- dynamic or limit usage of unknown to a module.
Warning: See http://www.swi-prolog.org/howto/database.html
true.

?- inex.
false.

?- set_prolog_flag(unknown, warning).
Warning: Using a non-error value for unknown in the global module
Warning: causes most of the development environment to stop working.
Warning: Please use :- dynamic or limit usage of unknown to a module.
Warning: See http://www.swi-prolog.org/howto/database.html
true.

?- inex.
Warning: toplevel: Undefined procedure: inex/0 (DWIM could not correct goal)
false.

正如您在上面所读到的,SWI 建议使用 dynamic 声明来代替 - 这反过来又存在其自身的问题......最好是声明:

:- discontiguous(y/1).

关于prolog - 关于解决意外 "Undefined procedure"错误的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42468128/

相关文章:

prolog - 如何在递归中使用差异列表?

prolog - Prolog如何指定pair打印格式

recursion - Prolog 二进制加法

prolog - 高效的 findall() 处理?

prolog - 获取列表中指定索引处的元素

Prolog/真假定义

prolog - 最好的 Prolog 编程实践和风格指南是什么?

prolog - 如何在 SWI Prolog 中参数化 SPARQL 查询?

list - 如何获取列表方案和序言的第一个、中间和最后一个元素?

list - 如何添加和比较列表中的成员