我对prolog很生疏,但我不确定为什么这样的事情会失败:
frack(3).
frack(X) :- frack(X-1).
所以,如果我评估frack(4)。从定义了上述事实的交互式提示中,我预计它不应该无休止地重复出现,因为4-1=3。但我在SWI Prolog中得到了这个错误:
ERROR: Out of global stack
试试看:
?- 4-1 = 3.
false.
为什么?因为4-1 = -(4, 1)
,它显然不是一个数字,而是一个复合项。
要推断Prolog中的整数,请使用clpfd约束,例如(使用GNU Prolog或B-Prolog):
|?-4-1#=X。X=3
在SWI Prolog中,图形跟踪器可能有助于您了解发生了什么:
?- gtrace, frack(4).
对于更复杂的调试,我建议失败切片,如false中所示;答复
以下是未终止的原因。您的查询不会终止,因为您的程序中有一个失败部分没有终止:
?-压裂(4)。frack(3):-false。压裂(X):-frack(X-1),false。
只能通过修改可见部分中的某些内容来解决此问题。三个SO答案建议使用(is)/2
。但这不会消除不终止!事实上,使用(is)/2
会产生本质上相同的片段:
?-压裂(4)。frack(3):-false。压裂(X):-Y是X-1,frack(Y),false。
至少,frack(4)
现在成功了,但它将在回溯时循环。为了避免不终止,您必须更改可见部分中的某些内容,例如X
的一些测试。有关详细信息,请参阅故障切片。
frack(X) :- frack(X-1).
应该是
frack(X) :- Y is X - 1, frack(Y).
按照您的编写方式,第一级的X-1
表达式将与下一级的X
变量统一在一起,而不会采用frack(3)
事实。
Prolog不进行算术运算,除非您使用is运算符:
frack(X) :- X1 is X-1, frack(X1).