Почему эта команда вызывает переполнение стека в прологе?

StackOverflow https://stackoverflow.com/questions/4836146

  •  27-10-2019
  •  | 
  •  

Вопрос

У меня есть следующий фрагмент кода 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). Анкет За X = 6, вместо этого происходит, поскольку ни одно правило не определяет предикат для fact(0,6), поиск начинается с fact(-1,V1), следовал с fact(-2,V2) и т. д. до тех пор, пока не произойдет матч для fact(-value, Var) где локальный результат будет найден.

Этого не может произойти, и бесконечная петля потребляет весь стек, пока ошибка не будет вызвана.

Другие советы

Причина почему fact(6) не заканчивается, можно найти в следующем :

?- fact(6).

num (0):- ЛОЖЬ.
num(X) :-
   num(X1), ЛОЖЬ,
   X is x1 + 1.

fact(X) :-
   num(Y), ЛОЖЬ,
   факт (y, x).

Потому что Этот фрагмент не заканчивается, а также ваша первоначальная программа не прекращается. Обратите внимание, что неверно не зависит от определения fact/2! В лучшем случае ваша программа может преуспеть, но она никогда не потерпит неудачу.

Подумайте об использовании Другое определение fact/2, что заканчивается также для fact(N, 6).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top