Получить callstack в Clojure - PullRequest
       21

Получить callstack в Clojure

20 голосов
/ 31 октября 2010

Когда я запускаю свои программы Clojure и получаю ошибку во время выполнения, я замечаю, что сообщение, напечатанное REPL, содержит только номер строки верхнего уровня из сценария, который я выполнил.Могу ли я заставить его сбросить стек вызовов (который ссылается на различные номера строк кода Clojure)?

Например:

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

Было бы лучше, если бы я знал больше, чем простовызов на высшем уровне (линия 206).

1 Ответ

29 голосов
/ 01 ноября 2010

Последнее выброшенное исключение доступно в *e var. Вы можете распечатать трассировку стека, вызвав .printStackTrace в Исключении. Он будет печатать номера строк, если ваше Исключение было сгенерировано исходным кодом в файле, или NO_SOURCE_FILE, если оно из REPL, как в моих примерах ниже.

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 (alpha) есть функция с именем 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 (например, SLIME для Emacs) автоматически выдают трассировку стека. Также есть несколько библиотек для отображения и управления стековыми трассами, например clojure.stacktrace и clj-stacktrace .

Обработка трассировки стека, кажется, является аспектом Clojure, который все еще совершенствуется.

...