Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tail Call Elimination in Clojure?

Can somebody rewrite this (plt) Scheme code into Clojure?

(define (f n)
   (printf "(f ~a)~n" n)
   (g n))

(define (g n)
   (printf "(g ~a)~n" n)
   (h n))

(define (h n)
   (printf "(h ~a)~n" n)
   (f (+ n 1)))

In such a way as to not collapse the procedures f, g, and h together and to allow the code to run indefinitely without crashing?

like image 232
tkf Avatar asked Feb 02 '10 04:02

tkf


People also ask

Does Clojure have tail call optimization?

Since Clojure uses the Java calling conventions, it cannot, and does not, make the same tail call optimization guarantees. Instead, it provides the recur special operator, which does constant-space recursive looping by rebinding and jumping to the nearest enclosing loop or function frame.

Does Clojure have tail recursion?

Tail Recursion In Clojure Unlike compilers of some other functional languages, Clojure's compiler will not automatically detect a recursive tail-call and optimise it accordingly. We need to make the tail call using a special form, recur , to explicitly utilise tail recursion optimisation.


1 Answers

Use a trampoline:

(declare f)

(defn h [n]
   (println "(h " n ")")
   #(f (+ n 1)))

(defn g [n]
   (println "(g " n ")")
   #(h n))

(defn f [n]
   (println "(f " n ")")
   #(g n))

Kick it off with:

(trampoline f 0)

I've had this code running on my pc in the background for about 5 hours now and the memory usage is flat.

like image 87
Nathan Hughes Avatar answered Oct 05 '22 04:10

Nathan Hughes