2010-07-27 6 views
17

, ev projelerimden birinde log4j kullanmaya başladı ve büyük bir modüldeki her işleve, (trace (str "entering: " function-name))'u kesmek ve yapıştırmak üzereydim. sonra aklın sesi yakalandı ve “daha ​​iyi bir yol var” dedi… Bir bütün fonksiyon bloğunu saran ve izleri onlara ya da buna benzer bir şey ekleyen bir makro yapmayı düşünebilir miyim? Bilge yığın-taşan-clojurians herhangi bir tavsiye?clojure: ad alanında her işlev için bir hata ayıklama izi ekleme?

cevap

17

bir makro gerek yoktur: benzer

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

... falan. En olası ekstra gereksinim, ifn? s olmayan şeyler için trace'u aramak için filter kullanmak olacaktır. Güncelleme: buna bir çözüm olarak düzenlenmiş (aynı zamanda makroların işlenmesi). 2. Güncelleme: bazı büyük hatalar düzeltildi. 4 Güncellemesi: eklenmiş görüntüleme işlevselliği.

Güncelleme 3: İşte benim repl gelen bir örnek:

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

Sadece Harikasın! ns-çözüm bölümünü açıklayabilir miydiniz? –

+0

:-) 'ns-resol' bir ad alanı veya ad alanı-adlandırma sembolü ve bir sembol alır ve (ikinci) sembol tarafından verilen isim altında verilen isim alanında bulunan Var'ı bulmaya çalışır. Burada önemli olan nokta, (1) Var'ın kök bağlanmasını değiştirmek mümkündür (bunu yapmanın bir kaç yolu vardır, fakat 'intern' burada ekstra meta verileri nasıl işlediğinden dolayı özellikle uygundur; Özgün için sarılmış bir işlevi geri vermek için yeniden bağlama kullanır) ve (2) Var'ın meta verilerini değiştirmek mümkündür (yani 'untraced-ns' mümkündür). –

+0

Yukarıdakilerin en son sürümü için http://gist.github.com/492764 adresine bakın (daha kullanışlı bir doküman hazırlamaya sahip!). –

İlgili konular