【发布时间】:2010-06-08 22:35:43
【问题描述】:
我想不出我需要它的情况。
【问题讨论】:
标签: prolog prolog-dif
我想不出我需要它的情况。
【问题讨论】:
标签: prolog prolog-dif
优雅的系统提供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([]). 将自动失败。没有必要为此目的引入一个永远不会成功的附加条款。
【讨论】:
显式失败。 fail 通常与 cut: ... !, fail. 结合使用以强制失败。
对于所有构造。 显式使用fail/false 来枚举通过回溯是一个非常容易出错的活动。考虑一个案例:
... ( generator(X), action(X), fail ; true ), ...
因此,这个想法是为所有X“做”动作。但是,如果action(X) 失败会发生什么?这个结构只是继续下一个候选人——就好像什么都没发生一样。通过这种方式,某些错误可能会在很长一段时间内未被检测到。
对于这种情况,最好使用失败的\+ ( generator(X), \+ action(X) ),如果action(X) 对某些X 失败。一些系统将其作为内置的forall/2 提供。就个人而言,我更喜欢在这种情况下使用\+,因为\+ 更清楚地表明该构造不会留下绑定。
Failure-slice. 出于诊断目的,将false 有意添加到您的程序中通常很有用。详情请见failure-slice。
【讨论】:
一个案例(取自Constraint Logic Programming using Eclipse)是not/1的实现:
:- op(900, fy, not).
not Q :- Q, !, fail.
not _ .
如果 Q 成功,cut (!) 会导致第二个 not 子句被丢弃,而 fail 确保否定结果。如果 Q 失败,则第二个 not 子句首先触发。
【讨论】:
fail 的另一个用途是在使用带有副作用的谓词时强制回溯:
writeall(X) :- member(A,X), write(A), fail.
writeall(_).
不过,有些人可能并不认为这种特别好的编程风格。 :)
【讨论】:
fail/0 是一个特殊的符号,当prolog遇到它作为目标时会立即失败。
fail 通常与 CUT(!) 结合使用以强制失败。
like(me,X) :- chess(X),!,fail.
like(me,X) :- games(X).
【讨论】: