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 Call to #'user/f did not conform to 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.* 因为在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}

如果我没漏掉什么,这种信息从解释数据中是可以获得的吗?我在解释数据中没有看到它,但也许它可以以某种方式恢复?无论如何,如果这种类型的信息可用,这将使打印更清晰的错误消息成为可能。

0
by

评论由:sohta

你好,这是否已经被CLJ-2392完成?:)

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