另一项 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> 不能转换为 clojure.lang.IFn...
)重写为易于理解的术语(期望一个函数 - 找到 <whatever>
)。
类似的动态挂钩用于过滤堆栈帧,以及将它们“打印”为字符串,这将为初学者提供更加友好的输出。