Skip to content

Instantly share code, notes, and snippets.

@GeorgeJahad
Forked from michalmarczyk/letrec.clj
Created July 23, 2010 04:45
Show Gist options
  • Save GeorgeJahad/487019 to your computer and use it in GitHub Desktop.
Save GeorgeJahad/487019 to your computer and use it in GitHub Desktop.
(defn tramp-fn [f]
(if (fn? f)
(fn [& args] #(apply f args))
f))
(defn tramp-fn2 [f]
(if (fn? f) (partial trampoline f) f))
(defmacro letrec [bindings & body]
(let [bcnt (quot (count bindings) 2)
arrs (gensym "bindings_array")
arrv `(make-array Object ~bcnt)
bprs (partition 2 bindings)
bssl (map first bprs)
bsss (set bssl)
bexs (map second bprs)
arrm (zipmap bssl (range bcnt))
btes (map #(prewalk (fn [f]
(if (bsss f)
`(tramp-fn (aget ~arrs ~(arrm f)))
f))
%)
bexs)]
`(let [~arrs ~arrv]
~@(map (fn [s e]
`(aset ~arrs ~(arrm s) ~e))
bssl
btes)
(let [~@(mapcat (fn [s]
[s `(tramp-fn2 (aget ~arrs ~(arrm s)))])
bssl)]
~@body))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment