Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Simpler debug-repl that works with unmodified Clojure
;; Inspired by George Jahad's version:
(defmacro local-bindings
"Produces a map of the names of local bindings to their values."
(let [symbols (map key @clojure.lang.Compiler/LOCAL_ENV)]
(zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))
(declare *locals*)
(defn eval-with-locals
"Evals a form with given locals. The locals should be a map of symbols to
[locals form]
(binding [*locals* locals]
`(let ~(vec (mapcat #(list % `(*locals* '~%)) (keys locals)))
(defmacro debug-repl
"Starts a REPL with the local bindings available."
:prompt #(print "dr => ")
:eval (partial eval-with-locals (local-bindings))))
;; Some examples
(let [c 1
locals (local-bindings)
d 2]
;; => {fn__5310 #<user$eval__5309 user$eval__5309@1a65a18>, c 1}
(let [c 1
d 2]
(defn a [b c]
(a "foo" "bar")
;; dr => c
;; "bar"
;; dr => d
;; 2
;; dr => *locals*
;; {fn__20 #<user$eval__19 user$eval__19@955cd5>,
;; c "bar",
;; d 2,
;; fn__22 #<user$eval__19$a__21 user$eval__19$a__21@59fb21>,
;; b "foo"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment