Хвостовая рекурсия в clojure

это код lisp, который использует хвостовую рекурсию.

(defun factorial (f n)
    (if (= n 1)
        f
        (factorial (* f n) (- n 1))))

я перевожу это в код clojure, ожидая такой же оптимизации рекурсии хвоста.

(defn fact [f n]
    (if (= n 1)
        f
        (fact (* f n) (dec n))))

однако я получил это целое переполнение (не переполнение стека) даже с небольшим числом, таким как (fact 1 30).

ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1374)

Я пытался с recur, но получил ту же ошибку.

(defn factorial [f n]
    (if (= n 1)
        f
        (recur (* f n) (dec n))))

что случилось с кодом clojure?

1 ответов


ничего, просто использовать BigInts:

(factorial 1N 30N) ;=> 265252859812191058636308480000000N

аргументы могут быть небольшими, но результата нет!

обратите внимание, что отмеченные версии арифметических операторов также доступны, которые поддерживают произвольную точность:

(reduce *' (range 1 31)) ;=> 265252859812191058636308480000000N