2024 Clojure 状态调查!分享你的想法吧!

欢迎!请参阅 关于页面以了解更多本网站的工作方式。

0
Clojure
当宏在 repl 处失败规范检查时,打印的消息包括 spec explain 生成的(通常是较大的)ex-data 映射。

Clojure 1.9.0-RC1
user=> (let [x] 5)
CompilerException clojure.lang.ExceptionInfo: 对 clojure.core/let 的调用未符合规范
In: [0] val: () 违规规范: :clojure.core.specs.alpha/bindings 在: [:args :bindings :init-expr]
预测器: any?,  输入不足
 #:clojure.spec.alpha{:problems [{:path [:args :bindings :init-expr], :reason "Insufficient input",}
:pred clojure.core/any?, :val (), :via [:clojure.core.specs.alpha/bindings
:clojure.core.specs.alpha/bindings], :in [0]}], :spec
#object[clojure.spec.alpha$regex_spec_impl$reify__1188 0x3f9270ed
"clojure.spec.alpha$regex_spec_impl$reify__1188@3f9270ed"], :value ([x] 5), :args ([x] 5)},
编译:(NO_SOURCE_PATH:18:1)

据我了解,Compiler.java 中的 checkSpecs 调用 spec 的 macroexpand-check。对于失败,macroexpand-check 抛出包含在数据映射中的 explain 数据的 ExceptionInfo。checkSpecs 捕获此并抛出一个新的 CompilerException,将 ExceptionInfo 作为原因。CompilerException 构造函数在原因上调用 toString,对于 ExceptionInfo 会生成包含消息和数据映射的字符串。

或许,可以添加一个 CompilerException 构造函数的新重载,该重载指定一个显式的消息和一个原因(使用 errorMsg 调用消息)。然后 checkSpecs 可以使用这个重载,传递 ExceptionInfo.getMessage 并避免打印数据映射。

我将它标记为主要问题,因为我认为数据映射的转储可能对新手来说相当令人畏惧。

2 个答案

0

评论由: alexmiller

导致输出消息混乱的原因有很多,我不同意提出的解决方案。CompilerExceptions是设计成带有位置信息的包装器(可以展开以查找异常原因),因此在一定程度上,REPL的catch处理器也应该承担一些责任——它应该做更多的工作来展开并报告。而且,如果有一个可以识别它们的标记,它甚至可以为特定于规格的错误做更多的事情。此外,我认为宏检查不应该包含解释数据字符串。

0
参考: https://clojure.atlassian.net/browse/CLJ-2272(由glchapman报告)
...