Skip to content

Instantly share code, notes, and snippets.

@nyuichi
Created May 19, 2011 15:44
Show Gist options
  • Save nyuichi/981070 to your computer and use it in GitHub Desktop.
Save nyuichi/981070 to your computer and use it in GitHub Desktop.
Tail Call Optimization in Clojure
(defn tco
[func]
(let [unique-id (gensym)
firstcall (ref true)
arguments (ref nil)
continue? (ref true)
answer (ref nil)]
(fn
[& args]
(if @firstcall
(dosync
(try
(ref-set firstcall false)
(ref-set arguments args)
(while @continue?
(let [r (apply func @arguments)]
(when-not (= r unique-id)
(ref-set continue? false)
(ref-set answer r))))
@answer
(finally
(ref-set continue? true)
(ref-set firstcall true))))
(dosync
(ref-set arguments args)
unique-id)))))
(def sum
(fn [n acc]
(if (zero? n)
acc
(sum (dec n) (+ acc n)))))
(def sum-tco
(tco
(fn [n acc]
(if (zero? n)
acc
(sum-tco (dec n) (+ acc n))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment