Hi, my name is Lambdebug. I can show you how a Clojure program is executed step by step. With a little trick I’ve learned from Einstein, I can even travel back in time, and show you the steps backwards.
It’s easy to meet me. Ask Mr Leiningen to get me from clojars (including
:dev-dependencies [[lambdebug "0.3.3"]] in your
project.clj) Then just say these sentences to the REPL,
=> (use 'lambdebug) => (debug '(+ 1 2))
And voilá, you’re right in the middle of my world. I even made the first step for you, you can see it highlighted.
Function: Given at REPL Form: ("+" 1 2) Result: #'clojure.core/+ >>>
You can step into this complicated expression typing
i, and learn the value of each number, then finally that
(+ 1 2) equals to
3. If you type
h, you’ll see all the directions I can take you.
>>> h Help: choose step (i)n, (n)ext, (b)ack, (p)rev, (o)ut
I can do more sophisticated things. Try a bit contrived example,
=> (debug '(doseq [i [10 0]] (try (+ (/ 1 y) 2) (catch ArithmeticException _ "oops"))))
When you first step through it,
i is bound to
10, and you’ll get the value of
(+ (/ 1 10) 2). On the secound round, an exception is thrown, so you won’t get to adding
2, but you land in the catch block, evaluating
I can see that you are not quite happy yet. You have written some nifty functions.
(ns nifty) (defn count-both [x y] (+ (count x) (count y))) (defn duplicate [x] (if (seq? x) (concat x x) [x x]))
No problem, I will follow you into any function defined in a file (with the exception of the
=> (use 'nifty) => (debug '(count-both  (duplicate )))
In case you want to know more about me, I am an open source person, you can come and see me at http://github.com/adamschmideg/lambdebug
I am not perfect
My limitations are,
- I don’t understand type hints.
- I respect privacy and I don’t mess with private functions.
- Did I say I hate feeling dizzy? No
- I am OK with most common macros, but not with trickier ones, like
- I am quite picky about java interop. I like simpler cases with dot notation, but no
doto, etc, please.
- No outer binding at the REPL, like
(let [answer 42] ...). It’s OK to bind a variable within a function, like
(for [i (range 9)] ...), or even
(map #(* 2 %) ...). It’s also OK to have them in a function defined in a file.
If you bump into a limitation, bug, annoyance not listed here, feel free let me know about it at http://github.com/adamschmideg/lambdebug/issues.
Do you want more?
Check out details.
Most recent blog posts
- 09 Oct 2010 » Integrated and distributed issue tracking
- 30 Aug 2010 » When picking a library, check how it's version-controlled
- 25 Aug 2010 » Rainbow debugging
- 19 Aug 2010 » Replace a substring and a subtree at the same time
- 17 Aug 2010 » My dreams of exception handling