В Scala 2.8.x добавлена новая аннотация (@tailrec
), которая дает ошибку времени компиляции, если компилятор не может выполнить оптимизацию хвостового вызова по аннотированному методу.Clojure warning/error при оптимизации оптимизации хвостового вызова
Есть ли аналогичные объекты в Clojure по отношению к loop/recur
?
EDIT: После прочтения первого ответа на мой вопрос (спасибо, Божидар Batsov) и далее искать в документации Clojure, я наткнулся на это:
(повторялись exprs *)
Оценивает exprs по порядку, то, параллельно, перепроверяет привязки точки рекурсии к значениям exprs. Если точкой рекурсии был fn-метод, то он перепроверяет параметры. Если точкой рекурсии был цикл, то он перепроверяет привязки цикла. Затем выполнение переходит к точке рекурсии. Выражение recur должно точно соответствовать арности точки рекурсии. В частности, если точка рекурсии была вершиной вариационного метода fn, то нет никакого сбора аргументов покоя - должен быть принят один seq (или null). Повтор в другом месте, кроме положения хвоста, является ошибкой.
Обратите внимание, что recur - это единственная конструкция, не занимающая стека, в Clojure. Оптимизация хвостового вызова отсутствует, и использование самозапуска для циклирования неизвестных границ не рекомендуется. recur является функциональным и его использование в хвостовом положении проверяется компилятором [акцент мой].
(def factorial
(fn [n]
(loop [cnt n acc 1]
(if (zero? cnt)
acc
(recur (dec cnt) (* acc cnt))))))
Этот ответ кажется мне вводящим в заблуждение. Точка цикла/рекурсия - это как раз ограниченная форма TCO, а именно TCO для саморекурсии (в функции или в форме цикла). Полностью общая TCO также будет оптимизировать использование стека для хвостовых вызовов для других функций. Таким образом, хотя у Clojure нет TCO (общая форма), у него есть собственные вызовы TCO из recur. Это то, о чем говорит «рекурсивный цикл цикла с постоянным пространством». В конечном счете, recur делает то же самое, что и @tailrec Scala, о чем и идет речь. (Здесь надеется, что этот вопрос уйдет с JDK7.) –
Думаю, вы не использовали Scala, что очень простая оптимизация хвоста происходит даже без tailrec, но вы получите сообщение об ошибке, если вы отметите метод как tailrec, то есть не на самом деле хвост-вызов рекурсивный. Ваш комментарий гораздо более вводящий в заблуждение, чем мой ответ, но каждый имеет право на мнение ... –
Итак, ваше мнение таково: «[t] здесь нет оптимизации хвостового вызова при использовании цикла/повтора», хотя сразу после сообщения вы цитируете отрывок из документов (как вы говорите), в котором говорится, что цикл с помощью 'recur' не потребляет стек? Кроме того, этот вопрос не касается поведения 'scalac', когда' @ tailrec' не указан, речь идет о возможности получения в Clojure рода гарантий '@ tailrec' дает вам Scala (вполне возможно, просто используйте' recur '). –