注意:明确地说,我提出以下问题的动机是学习如何绕过 Prolog 和 SWI-Prolog,而不是绕过特定的错误消息。事实上,我已经知道一种克服这个错误的方法。我的问题是询问是否还有其他几种替代方案。
我的 Prolog 教科书中的一个练习要求人们描述从几个查询中应该得到的结果,假设一个人事先咨询了以下知识库:
x(a).
z(b).
z(c).
z(d).
w(V) :- x(V).
w(V) :- y(V).
w(V) :- z(V).
Run Code Online (Sandbox Code Playgroud)
至少在 SWI-Prolog 上,这些查询中的大多数都失败了,因为 SWI-Prolog 解释y
为未定义。
从书末习题的解答我可以看出,这不是作者想要的结果。也许有一个 Prolog 实现,随着解决方案的出现,练习将转向它。
尽管如此,我想了解解决这个问题的好方法。
例如,考虑查询w(x).
。这本书的解决方案声称查询w(x).
应评估为false.
。事实上,事情是这样的:
?- w(x).
ERROR: w/1: Undefined procedure: y/1
Exception: (7) y(x) ?
Run Code Online (Sandbox Code Playgroud)
(此时,SWI-Prolog 期待我输入一些指示如何响应异常的字母。稍后会详细介绍。)
我正在寻找方法将上面的交互转变为
?- w(x).
false.
?-
Run Code Online (Sandbox Code Playgroud)
...或者至少<ONE-LETTER RESPONSE>
我可以给 SWI-Prolog一个合适的,以便它得出结论false
。IOW,所以
?- w(x).
ERROR: w/1: Undefined procedure: y/1
Exception: (7) y(x) ? <ONE-LETTER RESPONSE>
false.
?-
Run Code Online (Sandbox Code Playgroud)
我知道我的问题至少有一个答案,即简单地删除或注释掉该行:
w(V) :- y(V).
Run Code Online (Sandbox Code Playgroud)
我想知道其他可能的解决方案,例如我之前提到的“合适的”。
另一种可能性是一些 SWI-Prolog 全局配置,这将导致上述交互更改为
?- w(x).
false.
?-
Run Code Online (Sandbox Code Playgroud)
第三种可能性y
是以某种最小的方式“定义” 。我能想出的唯一方法是添加事实
y(dummy).
Run Code Online (Sandbox Code Playgroud)
到知识库。是否有一种更简单的定义方式y
,不需要在讨论领域引入一个无关的常数?
(这不是 SWI 特有的)
1970 年代的第一个 Prolog 系统实际上按照您描述的方式运行。很快就发现这是一个常见的错误来源。简单的拼写错误很长时间没有被发现。当前的实现会产生一个干净的存在错误。这是自 1995 年以来的标准行为。
但是,您可以使用unknown
具有三个值error
(默认值)fail
、 和的 ISO Prolog 标志回到旧时代warning
。
?- 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.
Run Code Online (Sandbox Code Playgroud)
正如您在上面所读到的,SWI 建议使用dynamic
声明来代替 - 这反过来有其自身的问题......改为声明要好得多:
:- discontiguous(y/1).
Run Code Online (Sandbox Code Playgroud)