请你在 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 中包含一个正则表达式(即 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.* 因为在 explain-data 中添加 fspec 可以使提供丰富错误信息给 {{*explain-out*}} 实现者成为可能。

同样适用于 {{macroexpand-check}}。

6 个答案

0

评论者:alexmiller

在本例中,fspec是指探讨中的规范,并且确实有一个:args组件(fspec实例通过ILookup提供对:args的关键字查找)。因此,虽然我想改进错误信息和数据,但我不同意从路径中移除:args。我认为有一件事可能会很有用,就是当工具失败时,可以更好地说明调用(将函数和参数组合成原始调用)。目前这些是分开的,需要一些心智工作来将参数列表重新编织在一起。

0

评论者:sohta

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

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

{quote}
我认为有一件事可能会很有用,那就是当工具失败时,可以更好地说明调用(将函数和参数组合成原始调用)。
{quote}

我完全同意这将是很有用的,尽管听起来它在一致性改进方面可能略超出此票的范围。

0

评论者:sohta

我制作了一个补丁来表达我的意思。任何反馈都将受到欢迎。

0

评论者:bbrinck

{quote}
我认为有一件事可能会有所帮助,就是当工具失败时,可以更好地说明调用(将函数和参数组合成原始调用)。目前这些是分开的,需要一些心智工作来将参数列表重新编织在一起。
{quote}

如果您错过了什么,我会感到抱歉,但能否从explain-data中获取函数?我没有在那里看到它,也许有某种方法可以恢复它?无论如何,如果您能提供此类信息,我将不胜感激,因为这将使打印更清晰的错误信息成为可能。

0

评论者:sohta

嘿,这个已经由 CLJ-2392 完成了吗? :)

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