Non ваши примеры получите быстрее, потому что если вы используете recur
вы уже сказать компилятору, что у вас есть хвост рекурсивной функции, и это позволяет компилятору генерировать байт-код, который использует goto
(как обычный императивный петли)
Есть некоторые преимущества, если JVM получает оптимизацию хвостового вызова.
Вы не придется использовать повторялись больше (если вы не хотите), так что вы можете написать функцию, как это (хвост рекурсивная функция)
(defn testfn [n] (when (not= 1000 n) (testfn n)))
Nowdays виртуальная машина не может обнаружить хвостовая рекурсия. С добавлением оптимизации хвостового вызова виртуальной машиной в состоянии видеть функцию выше так же, как если бы вы написали это (и, следовательно, получить скорость императивного цикла):
(defn testfn [n] (when (not= 1000 n) (recur n)))
Так что не так уж велики по улучшению, но есть другое случай, когда оптимизация хвостового вызова действительно велика.
Если у вас есть функции, вызывающие друг друга (иногда даже больше двух), и им не нужно удерживать стек (рекурсивный хвост), JVM может их оптимизировать. Это невозможно сейчас, потому что вы не можете сказать recur
, чтобы перейти к другой функции. Вот пример.
(defn even [n] (if (zero? n) true (odd? (dec n)))
(defn odd [n] (if (zero? n) false (even (dec n)))
Если вы попробуете это с большим количеством, знаете, что вы взорвите стек, но с оптимизацией вызывного хвоста вы не будете.
I have on немного дополнение левый. Существует функция называется trampoline
, что позволит вам сделать это уже (с небольшим изменением в стиле программирования и некоторые накладные расходы) Вместо объяснения trampoline
я отсылаю вас к блогу, который делает именно то, что:
http://pramode.net/clojure/2010/05/08/clojure-trampoline/