这是对从盒中提供的更佳错误信息的一个+1。
下面提到的库在某种程度上成功处理了症状,但让我们从一个想要学习Clojure、因此访问Clojure.org、点击“入门”的人的角度来看。
好的,我知道如何下载它。也许我会尝试通过使用repl.it
来感受一下它。
现在我有了基本经验(伴随着clojure.org上的令人困惑的错误信息)(参见:“你可能看到的一个令人困惑的错误信息是,意外地将数据列表当作代码进行评估的结果:”)
好吧,让我们先去学习Clojure。
好的,关于如何启动REPL,还是什么都没有。
第三个链接:启动REPL是个好主意。
第四个链接:这里有启动REPL的n种方式。
这里有其他运行REPL的方法。
但没有提到:如果你是初学者,让我们添加clj-stacktrace,然后启动REPL。
你明白这为什么不切实际吗?
我知道你近年来在编写更好的文档上投入了很多精力,我对指出这些事情感到抱歉。对于开发者而言,很难回到如此熟悉的东西,并用想要了解这种新语言的开发者视角去审视它。
我相信你有1到可能2次机会留下好印象,而能够说明用户出错原因的可读性错误信息正是其中重要的一部分。
user=> (map 1 inc)
不知道如何从clojure.core$inc创建ISeq
user=> (1 2 3)
执行错误(ClassCastException),在用户/eval7 (REPL:1)处。class java.lang.Long不能转换为class clojure.lang.IFn(java.lang.Long位于模块java.base的加载器'bootstrap'中;clojure.lang.IFn位于加载器'app'的无名模块中)
这两个都没有告诉我我犯了什么错误。它们告诉我一些关于lisp评估器如何在幕后工作的具体信息。(其中一些在clojure.org上有所记录)。
由于这些对我来说都没有帮助,作为一名新用户,我将去谷歌搜索。
对于初学者而言,谷歌搜索错误消息(如错误参数顺序或调用无法调用的内容的错误)的容忍度不高。
这就是你认为错误信息引导用户不是重要的印象所在。
(顺便提一下,你处理(nil 2 3)得很好,并没有抛出NPE)
这就是clojure实现(clojure)积极贡献到‘巨大学习曲线’这一说法的地方。
即使我经常看到这个错误,我也不认为我已经学会了它。(关于Sean的评论)。
伤害已经造成。
其他Clojure方言在这方面做得更好。(如CLJS和Sci)。
说到努力:有一种反对意见认为提供更好的错误信息会影响性能。如果我们在这里谈论异常处理(在上面两个例子中都是这样),
我不确定我理解性能影响的所在。
对于s-expr失败的异常处理不应该在性能关键路径上。
我很愿意更深入地了解性能方面是如何发挥作用的。
此外,对于上述两个示例错误消息,从用户的视角而不是从系统的视角编写它们的努力并不高。对于其中之一,意味着更改RT.java中的第557行。
更好的错误信息可能意味着捕获更底层的异常,将它们与当前的AST关联,并重新抛出,附带与导致错误的消息关联的列表元素。
我恳请你们引导初学者获得最好的REPL。
在入门教程和学习Clojure中将其设为默认。
然后你可以说:你知道,下面是IFn和ISeq,你可能会看到Java堆栈跟踪。
在Clojure的道路上,有许多新的概念需要学习和理解。重新解释错误信息不应该是最主要的一个。