7

我有以下序言代码片段:

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).
4

2 回答 2

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 的 a 。

这不可能发生,无限循环会消耗整个堆栈,直到触发错误。

于 2011-01-29T11:48:41.407 回答
2

不终止的原因fact(6)可以在下面的中找到:

?- 事实(6)。

数字(0):-。
数字(X):-
   num(X1), false ,
    X 是 X1 + 1。

事实(X):-
   数(Y),事实(Y,X)

因为这个片段不会终止,所以您的原始程序也不会终止。fact/2请注意,不终止与!的定义无关。充其量,您的程序可能会成功,但它永远不会(有限地)失败。

考虑使用的另一个定义fact/2,它也终止于fact(N, 6).

于 2012-11-15T11:47:55.480 回答