2010-10-31 16 views
19

Po uruchomieniu programów Clojure i otrzymaniu błędu podczas wykonywania, zauważam, że komunikat wydrukowany przez REPL zawiera tylko numer wiersza najwyższego poziomu ze skryptu, który wykonałem. Czy mogę zmusić go do zrzucenia stosu wywołań (który odwołuje się do różnych numerów linii kodu Clojure)?Uzyskiwanie wywołania zwrotnego w Clojure

Na przykład:

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

Byłoby ładniej gdybym wiedział więcej niż tylko połączenia górnego poziomu (linia 206).

Odpowiedz

28

Ostatni zgłoszony wyjątek jest dostępny w *e var. Możesz wydrukować ślad stosu, wywołując .printStackTrace w Exception. Wypisze numery linii, jeśli wyjątek został zgłoszony przez kod źródłowy w pliku, lub NO_SOURCE_FILE, jeśli pochodzi z REPL, jak w moich przykładach poniżej.

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 

W Clojure 1.3 (alfa) jest funkcją o nazwie pst który robi to samo. Te ślady stosu są nieco ładniejsze, ponieważ niektóre nieistniejące linie są usuwane.

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 

Pewne IDE (np. SLIME dla Emacsa) automatycznie wyskoczy na stosie. Istnieją również biblioteki do wyświetlania i manipulowania śladami stosu, takie jak clojure.stacktrace i clj-stacktrace.

Obsługa śledzenia stosu wydaje się być aspektem Clojure, który wciąż jest udoskonalany.

+0

Działa idealnie! :) – pauldoo

+0

Czy istnieje sposób na dostęp do poprzednich wyjątków, innych niż * e? – mascip

Powiązane problemy