Clojure编译时出现堆栈跟踪错误

3
我正在学习Clojure,我发现很难理解特定编译器错误发生的位置。
java.lang.ClassCastException: java.lang.Long cannot be cast to 
clojure.lang.IPersistentCollection, compiling:(fwpd/core.clj:100:1)

第100行只是:

(fib-seq3 5)

因为实际上错误出现在fib-seq3函数中(“conj”调用的参数被倒置了,请参见下文),所以它什么也没有说。

这是正常的吗?无法知道错误在哪里吗???

仅供参考,以下是代码(再次强调,我知道错误在哪里;我只是不明白应该如何找到它,因为信息并没有告诉我发生在哪一行):

(defn fib-seq3
  ([to]
   (fib-seq3 [] 0 1 0 to))
  ([coll a b k to]
    (if (= k to)
      coll
      (fib-seq3 (conj b coll) b (+ a b) (inc k) to)))

(fib-seq3 5)
2个回答

3

在Clojure中,堆栈跟踪很糟糕。事实上, Clojure社区将错误消息评为改进的最重要领域,也是最令人沮丧的部分

这个问题并不新鲜。Clojure堆栈跟踪相当长时间没有得到显着改进。但Clojure团队完全意识到了这种情况,因此我们可以期待有所改善。

为了更好地理解Clojure堆栈跟踪,请阅读初学者的Clojure堆栈跟踪。虽然这篇文章有点旧,但仍然相关。

简而言之,您应该寻找所谓的“原因跟踪”,它是任何Clojure堆栈跟踪的第二部分,并以“Caused by”短语开头。


我的问题不在于理解错误,而是理解错误出现的位置。在针对初学者的Clojure堆栈跟踪中,他得到了一个正确的堆栈跟踪:at stacktraces.core$make_sandwich.invoke(core.clj:4) at stacktraces.core$_main.invoke(core.clj:7),而我却在调用函数行上遇到了错误...而不是在被调用函数行上。 - Leo
1
@Leo,你在REPL中运行你的代码吗?Clojure的REPL通常只会打印出你的异常的根本原因。你可以使用clojure.stacktrace命名空间下的(print-cause-trace *e)来打印完整的错误信息跟踪。 - Leonid Beschastny
1
我强烈建议在使用默认截断堆栈跟踪的REPL时使用(.printStackTrace *e)。不要打印原因跟踪:您和堆栈跟踪之间插入的每个工具层都是在事情已经出错时可能会出现问题的另一件事。 - amalloy

1
问题在于我使用REPL(Vim + Fireplace)执行代码。通过使用 lein repl 来执行,问题得以解决。
@Leonid @amalloy: (.printStackTrace *e) 在REPL中(甚至从Fireplace内部使用“cqp”给出REPL提示符),可以提供正确的堆栈跟踪,因此非常感谢您的评论(不知道这一点!)。

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