如何避免使用整数基本情况进行非终止?

时间:2018-07-06 23:58:05

标签: prolog failure-slice

我想编写一个递归直到0的谓词,但始终无法终止。我使用失败切片将其范围缩小到了这个范围:

f(a, 0).
f(b, 0).
f(X, Y) :- false.

当我将文件加载为swipl -f test.pl,然后在提示符下运行f(X, 0).时,我得到了输出X = a,但看不到X = b或得到了新的提示。我希望它的行为像A is 1 + 1,在其中我得到A = 2.并带有句点和新的?-提示。

我能够使它像这样工作,但看起来并不干净:

f(X, 0) :- X = x.
f(X, Y) :- Y == 0 -> false; (NewY is Y - 1, f(X, NewY)).

对于列表,我可以将更一般的情况写为f(X, [A|B]),以确保仅在列表中至少包含一个元素时才适用。我是否可以做类似的事情来确保仅在Y不为0时才适用这里的一般情况?

我看过this question,虽然它暗示了正确的方向,但这也不起作用:

:- use_module(library(clpfd)).

int_int_prod(_, 0, 0).
int_int_prod(Num1, Num2, Result) :- 
    Num2 #> 0,
    NewNum2 #= Num2 - 1,
    int_int_prod(Num1, NewNum2, NewResult),
    Result #= Num1 + NewResult.

?- int_int_prod(0, 0, X).

1 个答案:

答案 0 :(得分:2)

运行f(X,0),您将得到X = a的回馈。注意空白。系统等待您的命令。

如果您按键盘上的;,它将以X = b进行响应。这是您不想发生的事情吗? (另一个选项是:按.)。毕竟,您的定义确实为该查询接受了{em>两个解决方案X=aX=b。为什么Prolog跳过第二个?不应该。

另一件事是,它仍然等待(在SWI中测试,通过[user]从提示符加载)在第二个结果之后等待用户响应。要消除那个,只需删除第三个子句。无论如何,这完全是多余的:在找不到更多匹配子句时,显式地失败会带来与失败相同的影响。

在没有第三条f(X,Y) :- false.的情况下,终止条件会改善:

6 ?- f(X,0).
X = a ;
X = b.
%   ^^    no white space, no waiting, immediate termination.