Переполнение стека происходит, потому что для вашего запроса предикат add/3
в конечном итоге вызывается с переменной как средний аргумент. Когда вы возвращаетесь в него, вы получаете цикл, который приводит к переполнению стека. Рассмотрим звонок add(X,Y,Z)
. Первое предложение дает вам первое решение, add(X,z,X)
. Но при возврате в исходное положение, когда вы используете второе предложение, вы объединяете свой запрос с add(X,s(Y),s(Z))
и рекурсивно вызываете add(X,Y,Z)
, туда, где вы начали (помните, что средний аргумент не создается, поэтому Y
в s(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)
...
Надеется, что это помогает.
Это действительно странное поведение, и трудно отследить ... Интересно, может ли артерия быть связана с ошибкой. – CapelliC