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 在: [: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中有一个regex(即f的参数的spec)作为{{::s/spec}}
- 每个问题包含{{:args}}在其{{:path}}中

这些事实可能导致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 是所指的规范,并且它确实有一个 component :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
...