Рекурсия хвоста в 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

Ничего, просто используйте BigInt s:

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

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

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

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