2010-10-31 25 views
19

Khi tôi chạy chương trình Clojure của mình và gặp lỗi trong khi thực hiện, tôi nhận thấy thông báo được in bởi REPL chỉ chứa số dòng cấp cao nhất từ ​​tập lệnh mà tôi đã thực hiện. Tôi có thể làm cho nó đổ một ngăn xếp cuộc gọi (tham chiếu đến các số dòng khác nhau của mã Clojure) không?Lấy một callstack trong Clojure

Ví dụ:

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

Nó sẽ đẹp hơn nếu tôi biết nhiều hơn là chỉ các cuộc gọi cấp cao nhất (đường 206).

Trả lời

28

Loại trừ ngoại lệ cuối cùng có sẵn trong số *e var. Bạn có thể in theo dõi ngăn xếp bằng cách gọi .printStackTrace về Ngoại lệ. Nó sẽ in số dòng nếu ngoại lệ của bạn được ném bởi mã nguồn trong một tệp hoặc NO_SOURCE_FILE nếu nó từ REPL, như trong ví dụ bên dưới của tôi.

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 

Trong Clojure 1,3 (alpha) có chức năng gọi là pst cũng giống như vậy. Các dấu vết ngăn xếp này đẹp hơn một chút vì một số dòng không liên quan được loại bỏ.

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 

Một số IDE nhất định (ví dụ: SLIME cho Emacs) sẽ tự động bật theo dõi ngăn xếp cho bạn. Ngoài ra còn có một số thư viện để hiển thị và điều khiển stacktraces, như clojure.stacktraceclj-stacktrace.

Xử lý theo dõi ngăn xếp có vẻ là một khía cạnh của Clojure vẫn đang được tinh chỉnh.

+0

Hoạt động hoàn hảo! :) – pauldoo

+0

Có cách nào để truy cập các trường hợp ngoại lệ trong quá khứ không, ngoại trừ * e? – mascip