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