Обрезки в конце рекурсивных предикатов в Прологе

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

  •  20-09-2019
  •  | 
  •  

Вопрос

pred(Args).
pred(Args) :-
    goalA,
    goalB,
    !,
    pred(Args).
pred(Args) :-
    goalC,
    goalD,
    !,
    pred(Args).

Обычно я бы написал рекурсивный предикат, который касался производительности памяти, что-то вроде приведенного выше фрагмента кода.При этом сокращение используется для того, чтобы попытаться принудительно выполнить оптимизацию хвостового вызова.Недавно я просматривал большую базу кода пролога и нашел несколько примеров, в которых вырезание фактически происходит после рекурсивного вызова, а не непосредственно перед ним.Предположительно, это скорее предотвращает оптимизацию хвостовых вызовов, чем помогает ей.

Мой вопрос: могу ли я переместить фрагмент после рекурсивного вызова непосредственно перед ним, не влияя на смысл программы?Это предполагает, что в каждом предложении сказуемого имеется сокращение в одном и том же относительном месте.

Теперь я еще немного об этом подумал, думаю, может быть, ответ «не обязательно», но, переписав весь код с вырезом перед вызовом и обнаружив, что набор тестов все еще проходит, я тоже интересно, может ли быть какая-то другая эзотерическая причина для написания подобных предикатов.Или это просто плохой код?

Это было полезно?

Решение

Я предполагаю, что это может быть плохое кодирование (или непонимание того, что делал автор).

Я говорю это потому, что сам однажды допустил ту же ошибку:

https://mailbox.iai.uni-bonn.de/mailman/public/swi-prolog/2009/001540.html

http://xonix.habrahabr.ru/blog/60430/ (предупреждение, на русском языке)

Но люди из списка рассылки SWI подтвердили, что правильный вариант кода с хвостовой рекурсией — это

head :-
       <guard goals>, !,
       <deterministic stuff>,
       head.
head :-
       ...
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top