У меня есть следующий код Clojure для вычисления числа с определенным «факториальным» свойством. (что именно код делает вторичным).
(defn factor-9
([]
(let [digits (take 9 (iterate #(inc %) 1))
nums (map (fn [x] ,(Integer. (apply str x))) (permutations digits))]
(some (fn [x] (and (factor-9 x) x)) nums)))
([n]
(or
(= 1 (count (str n)))
(and (divisible-by-length n) (factor-9 (quot n 10))))))
Теперь я в TCO и понимаю, что Clojure может обеспечить хвостовую рекурсию только в том случае, если это явно указано, используя ключевое слово recur
. Поэтому я переписал код для этого (замена фактора-9 на recur - единственное отличие):
(defn factor-9
([]
(let [digits (take 9 (iterate #(inc %) 1))
nums (map (fn [x] ,(Integer. (apply str x))) (permutations digits))]
(some (fn [x] (and (factor-9 x) x)) nums)))
([n]
(or
(= 1 (count (str n)))
(and (divisible-by-length n) (recur (quot n 10))))))
Насколько мне известно, ТШО имеет двойную выгоду. Первый состоит в том, что он не использует стек так сильно, как нерекурсивный вызов, и, следовательно, не использует его при больших рекурсиях. Во-вторых, я думаю, что, следовательно, он быстрее, поскольку его можно преобразовать в цикл.
Итак, я сделал очень грубый тест и не видел никакой разницы между этими двумя реализациями. Я ошибаюсь во втором предположении, или это как-то связано с работой на JVM (у которой нет автоматической TCO) и recur
с использованием трюка для достижения этой цели?
Спасибо.