我想编写一个递归直到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).
答案 0 :(得分:2)
运行f(X,0)
,您将得到X = a
的回馈。注意空白。系统等待您的命令。
如果您按键盘上的;
,它将以X = b
进行响应。这是您不想发生的事情吗? (另一个选项是:按.
)。毕竟,您的定义确实为该查询接受了{em>两个解决方案X=a
和X=b
。为什么Prolog跳过第二个?不应该。
另一件事是,它仍然等待(在SWI中测试,通过[user]
从提示符加载)在第二个结果之后等待用户响应。要消除那个,只需删除第三个子句。无论如何,这完全是多余的:在找不到更多匹配子句时,显式地失败会带来与失败相同的影响。
在没有第三条f(X,Y) :- false.
的情况下,终止条件会改善:
6 ?- f(X,0).
X = a ;
X = b.
% ^^ no white space, no waiting, immediate termination.