另一项 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...
这样的消息可以改写为更容易理解的初学者友好型语言(如 Expected a function - found a <whatever>
)。
类似的动态钩子用于筛选堆栈帧,并将“打印”它们到字符串中,将允许对初学者更为友好的输出。