为什么这个命令导致prolog中的堆栈溢出?

时间:2011-01-29 09:41:49

标签: prolog failure-slice

我有以下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).

2 个答案:

答案 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)

以下可以找到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).