2010-07-27 65 views
17

剛開始在我的一個家庭項目中使用log4j,我正準備打開鼠標並將(trace (str "entering: " function-name))剪切粘貼到大型模塊的每個功能中。那麼理智的聲音就被抓住了,並且說「這只是一種更好的方式」......我可以考慮製作一個包裝整個功能塊的宏,並將這些痕跡添加到它們或類似的東西中?來自明智的堆棧溢出clojurians任何意見?clojure:將調試跟蹤添加到名稱空間中的每個函數?

回答

17

無需宏:

(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)))) 

...或者類似的東西。最有可能的額外要求是使用filter,以便不在ifn? s上調用trace更新:在解決方案中編輯(也處理宏)。更新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 
+0

你根本真棒!你能解釋ns解析部分嗎? – 2010-07-27 18:43:02

+0

:-)'ns-resolve'需要一個命名空間或命名空間命名符號和一個符號,並試圖找到一個由(第二個)符號給出的名稱下的給定命名空間中的Var。這裏重要的一點是(1)可以改變Var的根綁定(有很多方法可以做到,但是intern在這裏特別方便,因爲它也處理額外的元數據; trace-ns (2)可以改變Var的元數據(所以'untraced-ns'是可能的)。 – 2010-07-27 18:51:24

+0

請參閱http://gist.github.com/492764獲取上述最新版本(以更有用的文檔字符串爲特色!)。 – 2010-07-27 19:56:53

相關問題