2010-10-31 45 views
19

當我運行我的Clojure程序並在執行期間出現錯誤時,我注意到由REPL打印的消息僅包含我執行的腳本中的頂級行號。我可以讓它轉儲一個調用堆棧(它引用了Clojure代碼的各種行數)嗎?在Clojure中獲取一個調用堆棧

例如:

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

這將是更好,如果我知道的不僅僅是頂級呼叫(線206)更多。

回答

28

拋出的最後一個異常在*e var中可用。您可以通過在例外上調用.printStackTrace來打印堆棧跟蹤。如果您的Exception是由源代碼引發的,它將打印行號,如果是來自REPL,則會打印NO_SOURCE_FILE,如下面的示例中所示。

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 

在Clojure中1.3(阿爾法)有一個名爲pst,做同樣的事情功能。這些堆棧軌跡更好一些,因爲一些無關的行被刪除。

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 

某些IDE(例如Emacs的SLIME)會自動彈出堆棧跟蹤。還有一些庫用於顯示和處理堆棧跟蹤,如clojure.stacktraceclj-stacktrace

堆棧跟蹤處理似乎是Clojure的一個方面,它仍在不斷完善。

+0

完美的作品! :) – pauldoo 2010-11-01 09:50:58

+0

有沒有辦法訪問過去的例外,而不是* e? – mascip 2014-07-21 19:29:23