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

欢迎!有关本站如何工作的更多信息,请参阅关于页面。

0
Spec
*描述*

假设我们想要遍历一个引发了一些规范错误的规范,从嵌入在 explain-data 中的根规范到最后导致错误的那个谓词。

我们通常可以使用 {{:path}} 信息在 explain-data 中达到这个目的


user=> (s/explain-data (s/tuple integer? string?) [1 :a])
#:clojure.spec.alpha{:problems
                     ({:path [1], ;; <- indicates the 1st subspec, ie. integer?, was the cause of the error
                       :pred clojure.core/string?,
                       :val :a,
                       :via [],
                       :in [1]}),
                     :spec ...,
                     :value [1 :a]}
user=>


如果我们沿着 {{:path}} 遍历规范树,最终可以到达引发规范错误的叶子谓词。

然而,在某些情况下,这可能不起作用,因为一些规范,例如 {{s/merge}}、{{s/and}} 和 {{s/&}},没有将任何线索放入 {{:path}} 中,告诉实际引发错误的子规范。


user=> (s/explain-data (s/merge (s/map-of integer? string?)
                                (s/coll-of (fn [[k v]] (= (str k) v))))
                       {1 "2"})
#:clojure.spec.alpha{:problems
                       ({:path [], ;; <- doesn't tell us anything at all
                       :pred (fn [[k v]] (= (str k) v)), ;; <- we don't know which subspec this pred occurs in
                       :val [1 "2"],
                       :via [],
                       :in [0]}),
                     :spec ...,
                     :value {1 "2"}}
user=>


为了在这些情况下达到我们的目的,我们必须做出一个非确定性选择:也就是说,任意选择一个子规范并尝试向下遍历它,如果在途中出现问题,就回溯到另一个子规范,依此类推。

根据我在执行库([仓库|
**建议**

为了更容易地实现规范遍历,此票据建议向 {{:path}} 添加索引,以指示哪个子规范为 {{s/merge}}、{{s/and}} 和 {{s/&}} 抛出规范错误,如下所示


user=> (s/explain-data (s/merge (s/map-of integer? string?)
                                (s/coll-of (fn [[k v]] (= (str k) v))))
                       {1 "2"})
#:clojure.spec.alpha{:problems
                     ({:path [1], ;; <- 表示第1个子规范,即 (s/coll-of (fn [[k v]] (= (str k) v))) 包含了错误的实际原因
                       :pred (fn [[k v]] (= (str k) v)),
                       :val [1 "2"],
                       :via [],
                       :in [0]}),
                     :spec ...,
                     :value {1 "2"}}
user=>


虽然这一增强确实是一个破坏性变更,但应极大地减少编写沿 {{:path}} 规范遍历代码所需的努力。

1 个答案

0
...