2024年Clojure现状调查!中分享您的想法。

欢迎!请参阅关于页面以了解有关此工作的更多信息。

+2
错误

Clojure的堆栈跟踪相当难以理解,有没有库可以显示更好的错误或格式化堆栈跟踪?

2 个答案

+1

有一些库可用于修改堆栈跟踪的打印,提供如折叠、Clojure框架和着色等功能。我们目前没有计划在下一个Clojure版本中进行这项工作。

你能指给我这些库是哪一个吗?
Michel,如果你还没有使用Clojure 1.10.1,我建议你升级。1.10对错误消息进行了大量工作,并在1.10.1中增加了更好的报告机制。

我还会分享Stuart Halloway在Twitter上关于堆栈跟踪的讨论链接: https://twitter.com/stuarthalloway/status/1148295437448876032

当你刚开始使用Clojure时,堆栈跟踪可能会令你感到害怕,但学会阅读它们是值得的。坦白说,折叠/省略它们对你帮助不大,因为有时重要信息被这些库隐藏了。
当我听说1.10中更好的错误消息时,这是我想会发生的事情
https://reasonml.github.io/blog/2017/08/25/way-nicer-error-messages.html

类似“ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn”这样的错误对新来的用户来说很神秘,请参阅: https://stackoverflow.com/questions/26720847/classcastexception-java-lang-long-cannot-be-cast-to-clojure-lang-ifn

对我来说,这里的价值在于能够指向用户源代码中的错误列和行,以便快速显示错误在嵌套事物中的位置。

然后要更好地以Clojure的术语而不是Java的术语解释错误发生的原因。我真的很不想听关于类的事情,因为在我看来,我的代码中没有类。(1 2 3)

话虽如此,我确实很天真,认为这是可行的。我们在这个语言中有大量的互操作性,这可能会使得这比在像elm这样的封闭系统中要困难得多。
by
Clojure _could_ detect these conditions and throw more informative exceptions, but this would add overhead to performance for everyone. Historically, we have always valued faster execution over "unusual" Java exceptions because each new comer only needs to learn them once, making it a good compromise for the majority of users.

However, it would be ideal to have a built-in "user-friendly" REPL option that uses the :caught keyword to provide more helpful error messages.
by
For example

user=> (defn easy [t]
                (clojure.main/repl-caught
                   (if (re-find #"cannot be cast to clojure.lang.IFn" (ex-message t))
                    (ex-info (str "Expected a function -- found: " (second (re-find #"^([^ ]*)" (ex-message t)))) {:cause t})
                    t)))
#'user/easy
user=> (clojure.main/repl :caught easy)
user=> (1 2 3)
Execution error (ExceptionInfo) at user/easy (REPL:1).
Expected a function -- found: java.lang.Long
user=>
+1
by

Another +1 for having even better error messages out of the box.

The libraries mentioned below are dealing with the symptoms somewhat successfully, but let's put ourselves in the shoes of someone wanting to learn Clojure, and thus turn to Clojure.org, click on Getting Started.

Alright, I now know how to download it. Perhaps I'll try it out using repl.it.
Now I have the basics experience (with somewhat confusing error messages according to clojure.org (see: "A confusing error you might see is the result of accidentally treating a list of data as if it were code:"))

Well, let's go to Learn Clojure first.
Ok, still nothing about how to launch a REPL.
第三链接:启动REPL是一个好主意。
第四链接:这里有启动REPL的n种方法。
这里有其他运行REPL的方法。

没有提到:如果你是初学者,让我们添加clj-stacktrace,然后再启动REPL。
你看出来这不太实用了吗?

我知道你在过去几年里为了更好的文档付出了很多努力,我来指出这些事情感觉很不好。回到这么熟悉的东西并从一个想学习这种新语言的开发者的角度看它很难。

我相信你有一次或两次的机会留下好印象,让可读的错误信息告诉你哪里搞错了是其中重要的一部分。

user=> (map 1 inc)
不知道如何从:clojure.core$inc创建ISeq。

user=> (1 2 3)
执行错误(ClassCastException)在user/eval7(REPL:1)。类java.lang.Long不能转换为类clojure.lang.IFn(java.lang.Long在模块java.base的loader 'bootstrap'中;clojure.lang.IFn在未命名的模块的loader 'app'中)。

这两者都没有告诉我哪里做错了。它们告诉我一些关于Lisp解释器背后的工作原理的细节。(其中一些在clojure.org上有文档)。

由于这些对我来说都没有帮助,作为新用户,我将谷歌搜索。
对于错误顺序错误或调用无法调用的错误之类的错误,初学者的谷歌搜索容忍度不高。

这就是错误信息引导用户不重要的印象产生的地方。
(顺便说一下,令人好奇的是,你已经在很好地处理(nil 2 3)而没有抛出NPE)

这就是Clojure(实现)积极促成“巨大学习曲线”明言的地方。
我不在乎——在看到这个错误很多次之后——我学会了它。(关于Sean的评论)。

伤害已经造成了。

其他的Clojure方言在这方面做得更好。(例如CLJS和Sci)。

说到努力:有人反对说提供更好的错误信息会影响性能。如果我们在这里讨论异常处理(在上述两个案例中我们都是在讨论它),
我不确定我理解性能影响的来源。
因为s-expr失败而进行的异常处理,我认为它不是性能关键路径。
我很高兴更好地理解性能层面是如何产生的。

此外,仅针对上面两个示例错误消息中的两个,从用户的观点而不是系统的观点来编写它们的努力并不大。对于其中一个来说,意味着更改RT.java的第557行。

更好的错误信息可能意味着捕获更底层的异常,将它们与当前的AST关联,并以与产生错误的消息列表元素相关联的方式重新抛出。

我强烈要求您引导初学者接触最好的REPL。
让它成为入门和学习Clojure的默认。
然后你可以拉回窗帘说:你知道,下面是IFn和ISeq,你可能会看到Java堆栈跟踪。

走Clojure路径时,有很多新的概念要学习和理解。重新解释错误信息不应该是其中之一。

by
这里还有一个Clojure新手遇到了ClassCastException问题。

https://www.reddit.com/r/Clojure/comments/gzudzn/problem_defining_fibonacci_function/
by
"好的,还是不知道如何启动REPL。" -- 在看到你对此答案的最新评论后,我意识到安装说明中没有提到安装后要做什么,因此我在入门页面提交了一个PR,增加了一条关于安装后运行clj或clojure以启动REPL的说明。Alex已经合并了它,所以我希望这能是一个小小的改进。
by
感谢,Sean。
对于我们这些已经熟悉这些概念的初学者来说,重新阅读文档并不简单。

在这方面,也许让用户直接在页面上提供对文档的反馈会有所帮助。许多公司在尝试改进面向非专家的文档时都会这样做。也许可以像这个版本一样添加一个反馈按钮:https://docs-feedback.aws.amazon.com/feedback.jsp?feedback_destination_id=068c0217-1615-4028-b3f7-7de2fb227b77&topic_url=https://aws.amazon.com/getting-started/hands-on/build-web-app-s3-lambda-api-gateway-dynamodb/module-one/
(作为一个例子)
...