Prolog 关于解决意外情况的方法;“未定义的程序”;错误

Prolog 关于解决意外情况的方法;“未定义的程序”;错误,prolog,Prolog,NB:我想澄清一下,我提出以下问题的动机是学习如何处理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勇敢地将

NB:我想澄清一下,我提出以下问题的动机是学习如何处理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.

?- 
…或者至少对于一个合适的
我可以给SWI Prolog,这样它就可以得出结论
false
。瞧,那么

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

?- 
我想知道其他可能的解决办法,例如,我刚才提到的“适当”办法

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

?- w(x).
false.

?- 
第三种可能是以某种最小的方式“定义”
y
。我能想出的唯一办法就是加上这个事实

y(dummy).

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

未定义的过程错误会引发异常,因此,如果您不想更改y/1谓词(删除或定义它),则希望引发异常您需要捕获异常,然后返回false,如下所示:

x(a).
z(b).
z(c).
z(d).
w(V) :- x(V).
w(V) :- catch(y(V), error(Err,_Context),my_handler(Err)).
w(V) :- z(V).


my_handler(Err):- write(Err),fail.
例如:

?- w(x).
existence_error(procedure,y/1)
false.
(这不是针对SWI的)

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

但是,您可以使用ISO Prolog标志
unknown
返回到旧版本,该标志有三个值
error
(默认值)、
fail
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.
如上所述,SWI建议使用
动态
声明来代替-这反过来也有其自身的问题。。。最好是声明:

:- discontiguous(y/1).

您可以使用指令
:-dynamic y/1将
y/1
声明为动态。
这会导致调用它的目标在不存在任何子句时失败。
:- discontiguous(y/1).