如何在 REPL 中读取 Clojure 异常?

7
很多时候,当我尝试编写某些函数时,会出现异常。这是很正常的。在Java中,您可以查找异常发生的位置和原因,但在Clojure中,异常文本让我感到困惑。有什么技巧可以帮助我阅读Clojure中的异常,并找到代码中异常发生的位置和原因吗?
例如,我将采取一些代码:
(do
 (list?)
 (list? [])
 (list? '(1 2 3))
 (list? (defn f [] (do ())))
 (list? "a"))

当我在REPL中调用此函数时,我将获得:
java.lang.IllegalArgumentException: Wrong number of args (0) passed to: core$list-QMARK- (NO_SOURCE_FILE:46)

第二行的问题很难通过此类信息找到原因,当代码稍微有些复杂时,它几乎无法提供任何信息。(当然,有时会提示查看列表中是否存在参数错误。)我在REPL中编写代码是错误的吗?如何在REPL中阅读异常信息?有办法在REPL中获得更好的异常信息吗?


可能是 https://dev59.com/f3E95IYBdhLWcg3wWMdQ 的重复问题。 - A. Webb
还与https://dev59.com/zuo6XIcBkEYKwwoYORwq#14298576有关。 - JohnJ
2个回答

6
你可以使用 clojure.stacktrace: http://richhickey.github.com/clojure/clojure.stacktrace-api.html 用法:
(use 'clojure.stacktrace)
(/ 1 0)
(e)

输出:

java.lang.ArithmeticException: Divide by zero
 at clojure.lang.Numbers.divide (Numbers.java:156)
    clojure.lang.Numbers.divide (Numbers.java:3691)
    user$eval954.invoke (NO_SOURCE_FILE:1)
    clojure.lang.Compiler.eval (Compiler.java:6511)
    clojure.lang.Compiler.eval (Compiler.java:6477)
    clojure.core$eval.invoke (core.clj:2797)
    clojure.main$repl$read_eval_print__6405.invoke (main.clj:245)
    clojure.main$repl$fn__6410.invoke (main.clj:266)
nil

2
获取 org.clojure/tools.trace
user=> (use 'clojure.tools.trace)

让我们尝试一下dotrace(改变顺序使事情更有趣):

user=> (dotrace [list?]
  #_=> (do
  #_=>  (list? [])
  #_=>  (list? '(1 2 3))
  #_=>  (list?)
  #_=>  (list? (defn f [] (do ())))
  #_=>  (list? "a"))
  #_=> )
IllegalStateException Can't dynamically bind non-dynamic var: clojure.core/list?
  clojure.lang.Var.pushThreadBindings (Var.java:353)

嗯...

user=> (.setDynamic #'list?)
#'clojure.core/list? 

让我们再试一次:

user=> (dotrace [list?]
  #_=>   (do
  #_=>   (list? [])
  #_=>   (list? '(1 2 3))
  #_=>   (list?)
  #_=>   (list? (defn f [] (do ())))
  #_=>   (list? "a")))
TRACE t1216: (list? [])
TRACE t1216: => false
TRACE t1217: (list? (1 2 3))
TRACE t1217: => true
TRACE t1218: (list?)
ArityException Wrong number of args (0) passed to: core$list-QMARK-  
  clojure.lang.AFn.throwArity (AFn.java:437)

啊哈!在异常之前成功到达(列表?)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接