Simple Tracing

12 views
Skip to first unread message

Rich Hickey

unread,
Apr 16, 2008, 8:18:47 PM4/16/08
to Clojure
This has been asked about a few times, and while it's not quite baked
for inclusion in the library, here's a simple tracing facility:

(def *trace-indent* 0)
(def traced (ref {})) ;var->original-fn
(def *trace* true)

(defn tracefn [v f]
(fn [& args]
(if *trace*
(binding [*trace* false]
(print (apply str (replicate *trace-indent* \space)))
(print ">> ")
(apply prn v args)
(let [ret
(binding [*trace-indent* (inc *trace-indent*)
*trace* true]
(apply f args))]
(print (apply str (replicate *trace-indent* \space)))
(print "<< ")
(prn v ret)
(flush)
ret))
(apply f args))))

(defmacro trace [f]
(let [v (resolve f)]
(dosync
(when (and v (not (@traced v)))
(let [f (.get v)]
(alter traced assoc v f)
(.bindRoot v (tracefn v f))))
`(keys @traced))))

(defmacro untrace [f]
(let [v (resolve f)]
(dosync
(when (and v (@traced v))
(.bindRoot v (@traced v))
(alter traced dissoc v))))
`(keys @traced))

(defn fact [n]
(if (zero? n) 1
(* n (fact (dec n)))))

(trace fact)

(fact 4)

>> #'user/fact 4
>> #'user/fact 3
>> #'user/fact 2
>> #'user/fact 1
>> #'user/fact 0
<< #'user/fact 1
<< #'user/fact 1
<< #'user/fact 2
<< #'user/fact 6
<< #'user/fact 24
24

(untrace fact)

Rich
Reply all
Reply to author
Forward
0 new messages