为什么这个命令在prolog中导致堆栈溢出?
我有以下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).
首先,看规则
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)
匹配fact(0,1)
。 对于X = 6
,反而会发生什么,因为没有规则定义fact(0,6)
的谓词,因此搜索以fact(-1,V1)
,然后是fact(-2,V2)
等。直到匹配发生了一个fact(-value, Var)
,其中本地结果将是Var找到的。
这不会发生,并且无限循环会消耗整个堆栈,直到触发错误。
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
的定义无关! 充其量,你的程序可能会成功,但它永远不会(有限)失败。
考虑使用fact/2
另一个定义,它也终止于fact(N, 6).
上一篇: Why does this command cause a stack overflow in prolog?