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

欢迎!请查看关于页面以了解更多关于这个工作方式的信息。

0
规范
*描述*

如果您对一个函数使用instrument,可能得到如下规范错误


(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不符合规范
;; In: [0] val: 3 失败在: [:args :x]谓词: 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的参数规范)作为 {{::s/spec}}
- 每个问题都包含它们自己的 {{:path}} 中的 {{:args}}

这些事实可能导致spec错误报错器产生混淆,因为f的参数规范({{(s/and integer? even?)}})没有与{{:args}}对应的子规范(我相信{{:path}}应该只包含可以用来指示从规范中选择哪个子规范的键)。

*可能的解决方案*

为了解决这种混淆的情况并提高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

评论者:sohta

嘿,这个功能是不是已经由CLJ-2392完成了?:)

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