Prolog中失败谓词的用途是什么?

时间:2010-06-08 22:35:44

标签: prolog prolog-dif

我无法想出我需要它的情况。

4 个答案:

答案 0 :(得分:19)

优雅系统提供false/0作为命令式fail/0的声明性同义词。一个有用的例子是当你手动想要强制回溯副作用时,例如:

?- between(1,3,N), format("line ~w\n", [N]), false.
line 1
line 2
line 3

您可以使用任何失败的目标,例如更短的目标,而不是false/0

?- between(1,3,N), format("line ~w\n", [N]), 0=1.
line 1
line 2
line 3

因此,false/0并非严格需要,但相当不错。

编辑:我有时会看到想要说明“我的关系不适用于空列表”的初学者,然后添加:

my_relation([]) :- false.

到他们的代码。这是必需,是使用false/0的一个很好的例子,例如在以编程方式生成的故障切片中。相反,专注于陈述关于你的关系持有的事情。在这种情况下,只需省略整个子句,并仅为非空列表定义关系,即至少有一个元素:

my_relation([L|Ls]) :- etc.

或者,如果您还要描述除列表之外的其他术语,请使用以下约束:

my_relation(T) :- dif(T, []), etc.

只给出这两个子句中的任何一个(或者两个),查询?- my_relation([]).将自动失败。没有必要引入一个从未成功的附加条款。

答案 1 :(得分:8)

显式失败。 fail通常与cut:... !, fail.一起使用以强制执行失败。

对于所有构造。显式使用fail / false来枚举通过回溯是一项非常容易出错的活动。考虑一个案例:

... ( generator(X), action(X), fail ; true ), ...

因此,我们的想法是为所有X“做”行动。但是,如果action(X)失败,会发生什么?这个结构只是继续下一个候选人 - 好像什么也没发生。通过这种方式,某些错误可能会长时间未被发现。

对于此类情况,最好使用失败的\+ ( generator(X), \+ action(X) ),如果某些action(X)失败X。有些系统将其作为内置forall/2提供。就个人而言,我更喜欢在这种情况下使用\+,因为\+更清楚一点,构造不会留下绑定。

故障切片。出于诊断目的,将false添加到您的程序中通常很有用。有关详细信息,请参阅

答案 2 :(得分:3)

失败的另一个用途是在使用具有副作用的谓词时强制回溯替代方案:

writeall(X) :- member(A,X), write(A), fail.
writeall(_).

有些人可能不会考虑这种特别好的编程风格。 :)

答案 3 :(得分:2)

一个案例(取自Constraint Logic Programming using Eclipse)是not / 1的实现:

:- op(900, fy, not).
not Q :- Q, !, fail.
not _ .

如果Q成功,cut(!)会导致第二个NOT子句被丢弃,并且失败会确保结果为负。如果Q失败,则第二个not子句首先触发。