为什么这个命令在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).

链接地址: http://www.djcxy.com/p/50245.html

上一篇: Why does this command cause a stack overflow in prolog?

下一篇: proprietary Web Application to MVC3/Entity