另一项 Clojure 状态调查和“错误信息”仍然是改进的首选。
Slack 上的讨论导致围绕异常和错误信息出现了一些针对初学者的具体痛点。我想在此着重关注的一个点是为(pst)
提供一个针对初学者的更友好的替代方案。
目前,(pst)
在一定程度上尝试去模糊化名称,消除“噪音”,并且缩小堆栈跟踪,但仍有很多方面需要改进,特别是对于初学者而言,他们发现自己难以理解某些异常,并且难以导航(Java 风格)的堆栈跟踪,尤其是与其他一些费尽心思提供用户友好错误信息和堆栈跟踪的语言相比。
Slack 中的一个例子
(defn f [i]
(fn [j]
(/ j i)))
(run! #(% 1) (map f (range 3)))
在 REPL 中打印的异常没问题,但(pst)
显示了:
user=> (pst)
ArithmeticException Divide by zero
clojure.lang.Numbers.divide (Numbers.java:190)
user/f/fn--16571 (NO_SOURCE_FILE:3)
user/eval16576/fn--16577 (NO_SOURCE_FILE:1)
clojure.core/run!/fn--8906 (core.clj:7849)
...
省略的部分提到了clojure.lang.ArrayChunk.reduce
,然后有多个对clojure.core.protocols
内容的引用(并且默认情况下没有足够深入以显示原始对clojure.core/run!
的调用)。
我认为这里存在一个机会来实现一个新的clojure.repl/explain
函数,它接受与pst
相同的参数,并提供了对故障的更详细解释,并且进一步减少了pst
当前显示的堆栈跟踪中的噪音。
理想情况下,这可以通过在核心中做一些基本的清理来实现,同时有一些动态钩子允许其他工具“安装”额外的扩展和/或清理,这样社区就可以提供库和功能来进一步改进初学者体验的这一方面。
例如,对ex-str
的动态钩子可以使社区提供的工具对异常消息进行美化(既有原 REPL 输入,也有pst
和explain
)。这样,初学者可能会遇到的困难消息,如class <whatever> cannot be cast to clojure.lang.IFn...
可以重写为更友好的语言(期望函数 - 找到 <whatever>
)。
类似的动态钩子可以过滤堆栈帧,并且将它们“打印”成字符串,这样就可以为初学者提供更友好的输出。