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

欢迎!请查看 关于 页面了解有关如何操作的更多信息。

0
Spec
*描述*

如果您使用 instrument 功能,可能会得到如下所示的 spec 错误:


(defn f [x] (inc x))
(s/fdef f
  :args (s/cat :x (s/and integer? even?))
  :ret (s/and integer? odd?))

(t/instrument)

(f 3)
;; ExceptionInfo 调用 #"user/f" 不符合 spec
;; In: [0] val: 3 fails at: [:args :x] predicate: even?
;; :clojure.spec.alpha/spec  #object[clojure.spec.alpha$regex_spec_impl$reify__1200
 0x19b3f9a "clojure.spec.alpha$regex_spec_impl$reify__1200@19b3f9a"]
;; :clojure.spec.alpha/value  (3)
;; :clojure.spec.alpha/args  (3)
;; :clojure.spec.alpha/failure  :instrument
;; :clojure.spec.test.alpha/caller  {:file "form-init3240393046310519022.clj", :lin
e 1, :var-scope user/eval1413}
;; clojure.core/ex-info (core.clj:4725)

(ex-data *e)
;; {:clojure.spec.alpha/problems
;;   [{:path [:args :x],
;;     :pred clojure.core/even?,
;;     :val 3,
;;     :via [],
;;     :in [0]}],
;;  :clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__1200 0x19b3f9a "clojure.spec.alpha$regex_spec_impl$reify__1200@19b3f9a"],
;;  :clojure.spec.alpha/value (3),
;;  :clojure.spec.alpha/args (3),
;;  :clojure.spec.alpha/failure :instrument,
;;  :clojure.spec.test.alpha/caller {:file "form-init3240393046310519022.clj", :line 1, :var-scope user/eval1413}}


如您所见,

- explain-data 包含一个正则表达式(即 f 的参数 spec),为 {{::s/spec}}
- 每个问题在它们的 {{:path}} 中包含 {{:args}}

这些事实可能会使 spec 错误报告者感到困惑,因为 f 的参数 spec({{(s/and integer? even?)}})没有与 {{:args}} 键对应的子 spec(我认为 {{:path}} 应只包含指示从 spec 中选择哪个子 spec 的线索的键)。

*可能的解决方案*

为了解决这种令人困惑的情况并提高 instrument 检查 explain-data 的一致性,我认为有以下两种选择:

- *解决方案 1.* 从 {{:path}} 中移除 {{:args}}
- *解决方案 2.* 修改 instrument 检查的 explain-data,使其具有 fspec(而不是它的 {{:args}})作为 {{::s/spec}}

我个人更喜欢 *解决方案 2.*,因为将 fspec 添加到 explain-data 可以使提供更丰富的错误信息给 {{\*explain-out\*}} 实现。

对于 {{macroexpand-check}} 也是如此。

6 答案

0

评论者:alexmiller

在这里,fspec 是我们讨论的规范,并且它具有一个组成部分 :args(fspec 实例支持使用 ILookup 对 :args 进行键查找)。因此,虽然我想改善这里的错误信息和数据,但我不赞成从路径中移除 :args。我认为一个有用的事情是,当仪器发生故障时,更好地说明调用(将函数和参数组合成原始调用)。目前这些是分开的,需要一些心理工作才能将参数列表重新拼接起来。

0

评论者:sohta

{quote}
虽然我想改善这里的错误信息和数据,但我不赞成从路径中移除 :args。
{quote}

是的,一旦我们决定采用解决方案 2,我认为就没有必要从 :path 中移除 {{:args}}。

{quote}
我认为一件有用的事情是,当仪器发生故障时,更好地说明调用(将函数和参数组合成原始调用)。
{quote}

我完全同意这会有所帮助,尽管从一致性的角度看,这听起来可能超出了这个票据的范围。

0

评论者:sohta

我已经提交了一个补丁来表达我的意思。任何反馈都将受到欢迎。

0

评论者:bbrinck

{quote}
我认为一件有用的事情是,当仪器发生故障时,更好地说明调用(将函数和参数组合成原始调用)。目前这些是分开的,需要一些心理工作才能将参数列表重新拼接起来。
{quote}

如果我已经错过了什么东西,请见谅,但是否可以从 explain-data 获取函数呢?我看不到它在 explain-data 里面,但也许它可以通过某种方式恢复?无论如何,我会非常感谢这种类型的信息可用,因为它将使得打印更清晰的错误信息成为可能。

0
by

评论者:sohta

嘿,这是否已经被CLJ-2392处理过了? :)

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