我有以下序言代码片段:
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.
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)
. 对于X = 6
,发生的事情是,因为没有规则定义谓词fact(0,6)
,所以搜索从 开始fact(-1,V1)
,然后是fact(-2,V2)
等等......直到匹配fact(-value, Var)
到本地结果将是找到的 Var 的 a 。
这不可能发生,无限循环会消耗整个堆栈,直到触发错误。
不终止的原因fact(6)
可以在下面的failure-slice中找到:
?- 事实(6)。数字(0):-假。 数字(X):- num(X1), false ,X 是 X1 + 1。 事实(X):- 数(Y),假,事实(Y,X)。
因为这个片段不会终止,所以您的原始程序也不会终止。fact/2
请注意,不终止与!的定义无关。充其量,您的程序可能会成功,但它永远不会(有限地)失败。
考虑使用的另一个定义fact/2
,它也终止于fact(N, 6).