2013-05-20 13 views
10

Questo è un codice Lisp che utilizza la ricorsione della coda.Ricorsione della coda in clojure

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

Traduco questo codice in clojure in attesa della stessa ottimizzazione della ricorsione in coda.

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

Comunque ho ottenuto questo integer overflow (non impilare overflow), anche con il piccolo numero, ad esempio (fact 1 30).

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

ho provato con recur, ma ho ottenuto lo stesso errore.

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

Cosa c'è di sbagliato con il codice clojure?

+7

Inoltre vale la pena notare che Clojure, a causa delle limitazioni della JVM, non supporta l'ottimizzazione automatica delle chiamate coda. 'recur' è davvero la strada da percorrere per un linguaggio ricorsivo in questo caso. – JohnJ

+0

In quali documenti del clojure posso trovare esempi di utilizzo ricorrenti senza loop? Il modo in cui lo hai usato qui. – SultanLegend

risposta

18

Niente, basta usare BigInt s:

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

Gli argomenti possono essere piccole, ma il risultato non è!

noti che spuntato versioni degli operatori aritmetici sono anche disponibili, che supportano precisione arbitraria:

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