发生堆栈溢出是因为,对于您的查询,add/3
最终调用谓词时使用一个变量作为中间参数。当你回溯到它时,你会得到一个导致堆栈溢出的循环。考虑电话add(X,Y,Z)
。第一个子句为您提供了第一个解决方案,add(X,z,X)
. 但是,在回溯时,当您使用第二个子句时,您将查询与add(X,s(Y),s(Z))
递归调用统一起来add(X,Y,Z)
,回到您开始的位置(请记住,中间参数没有被实例化,所以Y
ins(Y)
也不会在调用时被实例化。你是能够得到前四个解决方案,如上所示,这要归功于两个谓词的基本情况。当这些基本子句(在回溯时)的使用用尽时,你就会进入我刚刚解释过的循环。
尝试添加以下子句作为add/3
谓词的第一个子句:
add(X,Y,Z) :-
write('Called: '), writeq(add(X,Y,Z)), nl, fail.
重试你会得到的查询(希望你能很快Control-C
):
| ?- mult(X,Y,z).
Y = z ? ;
Called: add(_279,z,z)
X = z
Y = s(z) ? ;
Called: add(_279,z,_307)
Called: add(_279,_279,z)
X = z
Y = s(s(z)) ? ;
Called: add(_279,z,_309)
Called: add(_279,_279,_309)
Called: add(z,z,z)
X = z
Y = s(s(s(z))) ? ;
Called: add(s(_307),_307,_309)
Called: add(s(z),s(s(z)),z)
Called: add(s(s(_311)),_311,_313)
Called: add(s(s(z)),s(s(s(s(z)))),z)
Called: add(s(s(s(_315))),_315,_317)
Called: add(s(s(s(z))),s(s(s(s(s(s(z)))))),z)
Called: add(s(s(s(s(_319)))),_319,_321)
Called: add(s(s(s(s(z)))),s(s(s(s(s(s(s(s(z)))))))),z)
Called: add(s(s(s(s(s(_323))))),_323,_325)
...
希望这可以帮助。