我有以下prolog代码片段:
num(0).
num(X) :- num(X1), X is X1 + 1.
fact(0,1) :-!.
fact(X,Y) :- X1 is X-1, fact(X1,Y1), !, Y is Y1 * X.
fact(X) :- num(Y), fact(Y,X).
有人可以解释为什么以下命令导致堆栈溢出?提前谢谢。
fact(6).
答案 0 :(得分:2)
首先,看一下规则
num(0).
num(X) :- num(X1), X is X1 + 1.
谓词num(Y)
将立即对Y = 0
生效。
因此规则
fact(X) :- num(Y), fact(Y,X).
可以简化为
fact(X) :- fact(0,X).
将找到fact(0,1)
的匹配项。对于X = 6
,相反的是,由于没有规则定义fact(0,6)
的谓词,因此搜索以fact(-1,V1)
开头,然后是fact(-2,V2)
等......直到匹配为止发生在fact(-value, Var)
,其中本地结果将是Var找到的。
这不可能发生,并且无限循环会占用整个堆栈,直到触发错误。
答案 1 :(得分:2)
以下failure-slice可以找到fact(6)
未终止的原因:
?- fact(6).num(0) :- false. num(X) :- num(X1), false,X is X1 + 1. fact(X) :- num(Y), false,fact(Y,X).
因为此片段没有终止,所以原始程序也不会终止。请注意,非终止与fact/2
的定义无关!充其量,你的程序可能会成功,但它永远不会(有限地)失败。
请考虑使用another definition of fact/2
,该{{3}}也会终止fact(N, 6).