我在clojure.spec上的表现非常好。但是,我遇到了一个问题,在处理unform
时我无法解决这个问题。这是Hiccup让我们感动的一个松散的规范:
(require '[clojure.spec :as s])
(s/def ::hiccup
(s/and
vector?
(s/cat
:name keyword?
:attributes (s/? map?)
:contents (s/* ::contents))))
(s/def ::contents
(s/or
:element-seq (s/* ::hiccup)
:element ::hiccup
:text string?))
在我们被带走之前,让我们看看它是否适用于一个小案例。
(def example [:div])
(->> example
(s/conform ::hiccup))
;;=> {:name :h1}
像魅力一样工作。但是,我们可以撤消我们的一致性吗?
(->> example
(s/conform ::hiccup)
(s/unform ::hiccup))
;;=> (:div)
嗯,那应该是一个载体。我错过了什么吗?让我们看一下规范对此有何看法。
(->> example
(s/conform ::hiccup)
(s/unform ::hiccup)
(s/explain ::hiccup))
;; val: (:div) fails spec: :user/hiccup predicate: vector?
;;=> nil
确实,它失败了。所以问题是:如何使其正常工作?
答案 0 :(得分:0)
为了什么是值得的,我做了一个规范,检查一个向量并解开向量:
(s/def ::hiccup
(vector-spec
(s/cat
:name keyword?
:attributes (s/? map?)
:contents (s/* ::contents))))
在您的示例中,您可以像这样使用它:
Cert
答案 1 :(得分:0)
这里的最新回应。我没有意识到这个问题有多老,但是由于我已经写了答复,所以不妨提交它。
采用您为::hiccup
提供的规范:
(s/def ::hiccup
(s/and
vector?
(s/cat
:name keyword?
:attributes (s/? map?)
:contents (s/* ::contents))))
vector?
中的and
规范将根据该谓词测试输入数据。不幸的是,它并没有变成矢量。
您可以采取的补救措施是添加一个中间规范,该规范将在合规时充当标识,在不合规时充当所需角色。例如
(s/def ::hiccup
(s/and vector?
(s/conformer vec vec)
(s/cat
:name keyword?
:attributes (s/? map?)
:contents (s/* ::contents))))
(s/unform ::hiccup (s/conform ::hiccup [:div]))
;;=> [:div]
(s/conformer vec vec)
对于满足vector?
的所有内容都是禁忌,使用vec
作为协调器中的不合格函数将确保结果对不合格{{1 }} spec仍然是向量。
我是自我介绍的新手,这就是我如何按照您的意图工作的。请记住,规范设计者可能不会使用它。