Search code examples
debuggingclojure

How can I trace code execution in Clojure?


Why learning Clojure, I sometimes need to see what a function does at each step. For example:

(defn kadane [coll]
   (let [pos+ (fn [sum x] (if (neg? sum) x (+ sum x)))
         ending-heres (reductions pos+ 0 coll)]
     (reduce max ending-heres)))

Should I insert println here and there (where, how); or is there a suggested workflow/tool?


Solution

  • This may not be what you're after at the level of a single function (see Charles Duffy's comment below), but if you wanted to do get an overview of what's going on at the level of a namespace (or several), you could use tools.trace (disclosure: I'm a contributor):

    (ns foo.core)
    
    (defn foo [x] x)
    (defn bar [x] (foo x))
    
    (in-ns 'user) ; standard REPL namespace
    
    (require '[clojure.tools.trace :as trace])
    (trace/trace-ns 'foo.core)
    
    (foo.core/bar 123)
    TRACE t20387: (foo.core/bar 123)
    TRACE t20388: | (foo.core/foo 123)
    TRACE t20388: | => 123
    TRACE t20387: => 123
    

    It won't catch inner functions and such (as pointed out by Charles), and might be overwhelming with large code graphs, but when exploring small-ish code graphs it can be quite convenient.

    (It's also possible to trace individually selected Vars if the groups of interest aren't perfectly aligned with namespaces.)