Пролог: ошибка из глобального стека с тем, что мне кажется ОДНИМ уровнем рекурсии - PullRequest
4 голосов
/ 10 февраля 2012

Я довольно ржавый в прологе, но я не уверен, почему такие вещи терпят неудачу:

frack(3).

frack(X) :- frack(X-1).

Итак, если я оцениваю frack (4).из интерактивного приглашения с указанными выше фактами, я ожидаю, что он не должен бесконечно повторяться, так как 4-1 = 3. Но я получаю эту ошибку в SWI-Prolog:

ERROR: Out of global stack

Ответы [ 4 ]

5 голосов
/ 15 ноября 2012

Вот причина этого не прекращения. Ваш запрос не прекращается, потому что есть вашей программы, которая не завершается:

?- frack(4).

<s>frack(3) :- <b>false</b></s>.
frack(X) :-
   frack(X-1), <b>false</b>.

Вы можете исправить это, только изменив что-то в видимой части. Три SO-ответа предлагают использовать (is)/2. Но это не удалит не прекращение! Фактически, использование (is)/2 приводит к практически одинаковому фрагменту:

?- frack(4).

<s>frack(3) :- <b>false</b></s>.
frack(X) :-
   Y is X - 1,
   frack(Y), <b>false</b>.

По крайней мере, frack(4) теперь успешен, но он будет зацикливаться при возврате. Вы должны изменить что-то в видимой части, например, какой-нибудь тест для X, чтобы избежать не-прекращения. См. для получения дополнительной информации.

5 голосов
/ 10 февраля 2012

Попробуйте:

?- 4-1 = 3.
false.

Почему?Потому что 4-1 = -(4, 1), что явно не число, а составной термин.

Для рассуждений о целых числах в Прологе используйте, например, ограничения (используя GNU Prolog или B-Prolog):

| ?- 4-1 #= X.

<b>X = 3</b>

В SWI-Prolog графический трассировщик может быть полезен для просмотра происходящего:

?- gtrace, frack(4).

Для более сложной отладки я рекомендую как показано в ложном ответе .

3 голосов
/ 10 февраля 2012
frack(X) :- frack(X-1).

должно быть

frack(X) :- Y is X - 1, frack(Y).

Как вы написали, X-1 выражение первого уровня объединяет с переменной X на следующем уровне, никогда не переходя к факту frack(3).

2 голосов
/ 10 февраля 2012

Пролог не выполняет арифметику, если вы не используете оператор is:

frack(X) :- X1 is X-1, frack(X1).
...