2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请参阅 关于 页面以了解更多关于其工作方式的信息。

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

Clojure 1.9.0-RC1
user=> (let [x] 5)
编译器异常 clojure.lang.ExceptionInfo:调用 clojure.core/let 未符合规范
在:[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 抛出一个带有数据映射中解释数据的 ExceptionInfo 异常。checkSpecs 捕获这个异常并抛出一个新的 CompilerException,将 ExceptionInfo 作为原因。CompilerException 构造函数在原因上调用 toString,这就为 ExceptionInfo 生成一个包含消息和数据映射的字符串。

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

我将此标记为主要问题,因为我认为数据映射转储可能对新手具有震慑力。

2 答案

0

评论者:alexmiller

导致最终消息乱糟糟的原因有多个,我不赞同提出的解决方案。编译器异常(_compilerExceptions)被设计成带有位置信息的包装器(wrapper),可以展开以找到导致异常的原因,因此在一定程度上,REPL的捕获处理程序在这里也有一些责任 - 它应该做更多的工作来展开和报告。如果我们有一个标识这些错误的标记,它甚至可以为特定于规范错误做更多工作。此外,我认为宏检查不应该包括解释数据字符串。

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