My favourite method is a liberal sprinkling of println
s all over the code... Turning them on and off is easy thanks to the #_
reader macro (which makes the reader read in the following form, then pretend it's never seen it). Or you could use a macro expanding either to a passed-in body or nil
depending on the value of some special variable, say *debug*
:
(defmacro debug-do [& body]
(when *debug*
`(do ~@body)))
With a (def *debug* false)
in there, this will expand to nil
. With true
, it'll expand to body
wrapped in a do
.
The accepted answer to this SO question: Idiomatic Clojure for progress reporting? is very helpful when debugging sequence operations.
Then there's something which is currently incompatible with swank-clojure's REPL, but is too good not to mention: debug-repl
. You can use it in a standalone REPL, which is easy to get e.g. with Leiningen (lein repl
); and if you're launching your programme from the command line, then it's going to bring its own REPL up right in your terminal. The idea is that you can drop the debug-repl
macro in anywhere you like and have it bring up its own REPL when the programme's execution reaches that point, with all locals in scope etc. A couple of relevant links: The Clojure debug-repl, Clojure debug-repl tricks, how 'bout a debug-repl (on the Clojure Google group), debug-repl on Clojars.
swank-clojure does an adequate job of making SLIME's built-in debugger useful when working with Clojure code -- note how the irrelevant bits of the stacktrace are greyed out so it's easy to find the actual problem in the code being debugged. One thing to keep in mind is that anonymous functions without "name tags" appear in the stacktrace with basically no useful information attached to them; when a "name tag" is added, it does appear in the stacktrace and all is well again:
(fn [& args] ...)
vs.
(fn tag [& args] ...)
example stacktrace entries:
1: user$eval__3130$fn__3131.invoke(NO_SOURCE_FILE:1)
vs. ^^
1: user$eval__3138$tag__3139.invoke(NO_SOURCE_FILE:1)
^^^