这是对即使更好的出错信息的一个+1。
下面提到的库在某种程度上成功地治疗了症状,但让我们从一个想学习Clojure的人的角度来看,他们来到Clojure.org,点击开始。
好的,我现在知道了如何下载它。也许我会尝试通过使用repl.it
来感受它。
现在我有了基本经验(带有clojure.org中令人困惑的错误消息——见“你可能看到的一个令人困惑的错误是尝试将一组数据评估为代码的结果:”)
好吧,我们先学习Clojure。
好的,还是没有关于如何启动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位于名为'app'的无名module中)。
两者都没有告诉我我哪里做错了。它告诉我一些关于如何后台工作lisp解释器的一些具体信息。(其中一些在clojure.org上有文档说明)。
由于这些都没有对我这个新用户有所帮助,我将去Google搜索。
对于错误,如错误的参数顺序或调用无法调用的内容,初学者对搜索错误信息的容忍度很低。
这就是你留下的印象,即用户引导错误消息并不重要。
(顺便说一下,你处理(nil 2 3)相当出色,并没有抛出NPE)
这就是clojure(实现)积极地为“巨大的学习曲线”做法做出贡献的地方。
我无法理解这个问题在哪里——尽管看了很多次这个错误,我最终还是学会了是什么——(关于Sean的评论)。
损害已经造成了。
其他Clojure方言在这里做得更好。(例如CLJS和Sci)。
说到努力,有一种反对意见认为提供更好的错误消息会影响性能。如果我们在这里谈论异常处理(以及在上面两个例子中我们确实这样做),
我不确定我懂性能影响在哪里。
由于s-expr失败而进行的异常处理,我认为这不在性能关键路径上。
很高兴更好地理解性能方面是如何发挥作用的。
仅仅为了上述两个示例错误消息,从用户的视角出发而不是系统的视角来编写它们的努力并不大。对于其中一个,意味着更改RT.java第557行
更好的错误消息可能意味着捕获低级异常,将它们与当前的AST关联,并重新抛出与生成错误的列表元素相关的消息。
我恳请你引导初学者到达他们能获得的最优秀的REPL。
让它成为入门和学习Clojure时的默认。
然后你可以拉下帷幕说:你知道,下面是IFn和ISeq,你可能还会看到Java堆栈跟踪。
在追随Clojure的道路时,有很多新概念要学习和理解。重新解释错误消息不应该成为其中之一。