ha appena iniziato a utilizzare log4j in uno dei miei progetti di casa e stavo proprio per rompere il mouse e tagliare e incollare (trace (str "entering: " function-name))
in ogni funzione in un modulo di grandi dimensioni. poi la voce della ragione è arrivata e ha detto "semplicemente deve esserci un modo migliore" ... Posso pensare di creare una macro che avvolge un intero blocco di funzioni e aggiunge le tracce a loro o qualcosa del genere? Qualche consiglio dai saggi clojuriani stracolmi di pila?clojure: aggiunta una traccia di debug ad ogni funzione in un namespace?
17
A
risposta
17
Non c'è bisogno di una macro:
(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))))
... o qualcosa di simile. Il requisito aggiuntivo più probabile sarebbe quello di utilizzare filter
in modo da non chiamare trace
su cose che non sono ifn?
s. Aggiornamento: modificato in una soluzione (anche gestendo macro). Aggiornamento 2: corretto alcuni bug importanti. Aggiornamento 4: aggiunta funzionalità di annullamento.
Update 3: Ecco un esempio dalla mia 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
Problemi correlati
- 1. clojure - codice di eval in diversi namespace
- 2. Fare un namespace nome di funzione qualificato in una macro
- 3. una funzione ricorsiva di Fibonacci in Clojure
- 4. Debug in Clojure?
- 5. Clojure: chiamare una funzione per ogni elemento in un vettore con esso indice
- 6. Ottenere namespace in una funzione statica
- 7. Esclude java.lang. * Nel namespace Clojure
- 8. chiamata di una funzione utilizzando namespace
- 9. Applicare un elenco di funzioni ad una corrispondente lista di dati in Clojure
- 10. Debug dei dati in "namespace anonimi" (C++)
- 11. Aggiunta di un dizionario ad un altro
- 12. Immettere un set di punti per una funzione di clojure
- 13. Clojure <> ClojureScript; Ad esempio: la funzione "formato"
- 14. aggiunta di controller con un namespace admin come sottocartella
- 15. Aggiunta di attributi aggiuntivi per ogni proprietà di una classe
- 16. Esiste una funzione che accetta un elenco di elenchi di argomenti e applica ogni elenco a una determinata funzione?
- 17. applicare una funzione Word32 ad un ByteString
- 18. Come convertire una stringa in una funzione in Clojure?
- 19. Come si fa il debug di Clojure in NetBeans IDE?
- 20. Aggiunta di una stringa davanti a una stringa per ogni elemento in un elenco in python
- 21. Generazione dinamica di funzioni ad alte prestazioni in clojure
- 22. Esecuzione di una funzione associata dinamicamente in Clojure
- 23. nomi di stampa di variabili passate ad una funzione
- 24. Aggiunta di un valore ad una lista che si basa su un modello
- 25. Aggiunta ListItems ad una DropDownList da un elenco generico
- 26. Come elencare le funzioni di un namespace?
- 27. come restituire una funzione clojure come stringa
- 28. È possibile decomporre una funzione Clojure?
- 29. Applicando putStr ad ogni elemento di un elenco
- 30. Perché clojure aggiunge qualificatori di namespace ai nomi all'interno di un backquote?
Sei semplicemente impressionante! potresti spiegare la parte di risoluzione dei problemi? –
:-) 'ns-resolve' prende uno spazio dei nomi o un nome di namespace e un simbolo e tenta di trovare un Var internato nello spazio dei nomi specificato sotto il nome dato dal (secondo) simbolo. Il punto importante qui è che (1) è possibile cambiare il binding della radice del Var (c'è un certo numero di modi per farlo, ma 'intern' è qui particolarmente conveniente a causa del modo in cui gestisce anche i metadati extra;' trace-ns' usa il rebinding per sostituire una funzione avvolta per l'originale) e (2) è possibile cambiare i metadati del Var (è possibile che 'non-ns 'sia possibile). –
Vedere http://gist.github.com/492764 per la versione più recente di sopra (con una docstring più utile!). –