在 Clojure 中获取调用堆栈

发布于 2024-09-29 20:22:44 字数 322 浏览 2 评论 0原文

当我运行 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 行),那就更好了。

When I run my Clojure programs and get an error during execution, I notice that the message printed by the REPL only contains the top level line number from the script I executed. Can I get it to dump a call stack (which references the various line numbers of Clojure code)?

For example:

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

It would be nicer if I knew more than just the top level call (line 206).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我们只是彼此的过ke 2024-10-06 20:22:44

最后抛出的异常可在 *e var 中找到。您可以通过在异常上调用 .printStackTrace 来打印堆栈跟踪。如果您的异常是由文件中的源代码引发的,它将打印行号;如果来自 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 (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(例如 Emacs 的 SLIME)会自动为您弹出堆栈跟踪。还有一些用于显示和操作堆栈跟踪的库,例如 clojure.stacktraceclj-stacktrace

堆栈跟踪处理似乎是 Clojure 仍在完善的一个方面。

The last Exception thrown is available in the *e var. You can print a stack trace by calling .printStackTrace on the Exception. It'll print line numbers if your Exception was thrown by source code in a file, or NO_SOURCE_FILE if it's from the REPL, like in my examples below.

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) there's a function called pst that does the same thing. These stack traces are a bit nicer because some extraneous lines are removed.

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

Certain IDEs (e.g. SLIME for Emacs) will pop up the stack trace for you automatically. There are also some libraries for displaying and manipulating stacktraces, like clojure.stacktrace and clj-stacktrace.

Stack trace handling seems to be an aspect of Clojure that's still being refined.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文