2010-06-08 72 views

回答

16

优雅的系统提供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([]).将自动失效。没有必要引入一个额外的条款,为此目的从来没有成功。

+0

s /优雅/优雅和符合/ – false 2016-03-31 13:44:32

2

一种情况(从Constraint Logic Programming using Eclipse采取)是不/ 1的实施方式:(!)

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

如果Q成功,则切口使第二不子句被丢弃,和故障确保负结果。如果Q失败,则第二个非子句首先触发。

1

另一个用途的失败是强制使用带有副作用的谓词时通过替代回溯:

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

有些人可能不考虑,虽然这个特别良好的编程风格。 :)

+0

糟糕,看起来像席子打我。 – hdan 2010-06-09 22:05:16

7

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

对于所有结构。明确使用fail/false来枚举通过回溯是一个非常容易出错的行为。考虑一个案例:

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

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

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

失败切片。出于诊断目的,将false添加到您的程序中通常很有用。有关更多详细信息,请参见