2010-10-31 12 views
19

Quando eseguo i miei programmi Clojure e ottengo un errore durante l'esecuzione, noto che il messaggio stampato dal REPL contiene solo il numero di riga di livello superiore dello script che ho eseguito. Posso farlo per scaricare uno stack di chiamate (che fa riferimento ai vari numeri di riga del codice Clojure)?Ottenere un callstack in Clojure

Ad esempio:

user=> (load-file "test.clj") 
java.lang.IllegalArgumentException: Wrong number of args (1) passed to: user$eval134$fn (test.clj:206) 
user=> 

Sarebbe bello se sapevo più che solo la chiamata di livello superiore (linea 206).

risposta

28

L'ultima eccezione generata è disponibile nella variabile *e. È possibile stampare una traccia stack chiamando .printStackTrace nell'eccezione. Stampa i numeri di riga se la tua eccezione è stata generata dal codice sorgente in un file, o NO_SOURCE_FILE se proviene dal REPL, come nei miei esempi qui sotto.

Clojure 1.2.0 
user=> (throw (Exception. "FOO")) 
java.lang.Exception: FOO (NO_SOURCE_FILE:0) 
user=> *e 
#<CompilerException java.lang.Exception: FOO (NO_SOURCE_FILE:0)> 
user=> (.printStackTrace *e) 
java.lang.Exception: FOO (NO_SOURCE_FILE:0) 
     at clojure.lang.Compiler.eval(Compiler.java:5440) 
     at clojure.lang.Compiler.eval(Compiler.java:5391) 
     at clojure.core$eval.invoke(core.clj:2382) 
     at clojure.main$repl$read_eval_print__5624.invoke(main.clj:183) 
     at clojure.main$repl$fn__5629.invoke(main.clj:204) 
     at clojure.main$repl.doInvoke(main.clj:204) 
     at clojure.lang.RestFn.invoke(RestFn.java:422) 
     at clojure.main$repl_opt.invoke(main.clj:262) 
     at clojure.main$main.doInvoke(main.clj:355) 
     at clojure.lang.RestFn.invoke(RestFn.java:398) 
     at clojure.lang.Var.invoke(Var.java:361) 
     at clojure.lang.AFn.applyToHelper(AFn.java:159) 
     at clojure.lang.Var.applyTo(Var.java:482) 
     at clojure.main.main(main.java:37) 
Caused by: java.lang.Exception: FOO 
     at user$eval1.invoke(NO_SOURCE_FILE:1) 
     at clojure.lang.Compiler.eval(Compiler.java:5424) 
     ... 13 more 
nil 

In Clojure 1.3 (alpha) c'è una funzione chiamata pst che fa la stessa cosa. Queste tracce di stack sono un po 'più carine perché alcune linee estranee vengono rimosse.

Clojure 1.3.0-master-SNAPSHOT 
user=> (throw (Exception. "FOO")) 
Exception FOO user/eval1 (NO_SOURCE_FILE:1) 
user=> (pst) 
Exception FOO 
     user/eval1 (NO_SOURCE_FILE:1) 
     clojure.lang.Compiler.eval (Compiler.java:5998) 
     clojure.lang.Compiler.eval (Compiler.java:5965) 
     clojure.core/eval (core.clj:2652) 
     clojure.core/eval (core.clj:-1) 
     clojure.main/repl/read-eval-print--5575 (main.clj:178) 
     clojure.main/repl/fn--5580 (main.clj:199) 
     clojure.main/repl (main.clj:199) 
     clojure.main/repl-opt (main.clj:257) 
     clojure.main/main (main.clj:350) 
     clojure.lang.Var.invoke (Var.java:361) 
     clojure.lang.Var.applyTo (Var.java:482) 
nil 

Alcuni IDE (ad esempio SLIME per Emacs) popoleranno automaticamente la traccia dello stack. Ci sono anche alcune librerie per la visualizzazione e la manipolazione di stacktrace, come clojure.stacktrace e clj-stacktrace.

La gestione delle tracce di stack sembra essere un aspetto di Clojure che è ancora in fase di perfezionamento.

+0

Funziona perfettamente! :) – pauldoo

+0

Esiste un modo per accedere alle eccezioni precedenti, diverse da * e? – mascip