clojure:为命名空间中的每个函数添加调试跟踪?

Art*_*ldt 17 clojure

刚开始在我的一个家庭项目中使用log4j,我就要打破鼠标并剪切并粘贴 (trace (str "entering: " function-name))到大型模块中的每个功能中.然后理智的声音赶上并说"只需要一个更好的方法"......我可以想到制作一个包含整个功能块的宏并为它们添加痕迹或类似的东西?任何明智的Stack-overflow-clojurians的建议?

Mic*_*zyk 18

不需要宏:

(defn trace-ns
  "ns should be a namespace object or a symbol."
  [ns]
  (doseq [s (keys (ns-interns ns))
          :let [v (ns-resolve ns s)]
          :when (and (ifn? @v) (-> v meta :macro not))]
    (intern ns
            (with-meta s {:traced true :untraced @v})
            (let [f @v] (fn [& args]
                          (clojure.contrib.trace/trace (str "entering: " s))
                          (apply f args))))))

(defn untrace-ns [ns]
  (doseq [s (keys (ns-interns ns))
          :let [v (ns-resolve ns s)]
          :when (:traced (meta v))]
    (alter-meta! (intern ns s (:untraced (meta v)))
                 #(dissoc % :traced :untraced))))
Run Code Online (Sandbox Code Playgroud)

......或类似的东西.最可能的额外要求是使用,filter以便不要调用traceifn?s的东西.更新:在解决方案中编辑(也处理宏).更新2:修复了一些主要错误.更新4:添加了untrace功能.

更新3:这是我的REPL的一个例子:

user> (ns foo)
nil
foo> (defn foo [x] x)
#'foo/foo
foo> (defmacro bar [x] x)
#'foo/bar
foo> (ns user)
nil
user> (trace-ns 'foo)
nil
user> (foo/foo :foo)
TRACE: "entering: foo"
:foo
user> (foo/bar :foo)
:foo
user> (untrace-ns 'foo)
nil
user> (foo/foo :foo)
:foo
Run Code Online (Sandbox Code Playgroud)