10

This is a lisp code that uses tail recursion.

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

I translate this into clojure code expecting the same tail recursion optimization.

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

However I got this integer overflow (not stack overflow) even with small number such as (fact 1 30).

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

I tried with recur, but got the same error.

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

What's wrong with the clojure code?

2
  • 7
    Also it's worth noting that Clojure, because of limitations of the JVM, doesn't support automatic tail call optimization. recur is indeed the way to go for a recursive idiom in this case. Commented May 20, 2013 at 18:40
  • 1
    Where in the clojure docs can I find examples of using recur without loop? The way you have used it here. Commented Jun 9, 2017 at 17:01

1 Answer 1

18

Nothing, just use BigInts:

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

The arguments may be small, but the result is not!

Note that ticked versions of the arithmetic operators are also available, which support arbitrary precision:

(reduce *' (range 1 31)) ;=> 265252859812191058636308480000000N
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.