I did a great job with clojure.spec for the most part. However, I ran into a problem that I could not understand when working with unform. Here is a free spec for Hiccup to make us move:
(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?))
Now, before we leave, let's see if it works with a small passing case.
(def example [:div])
(->> example
(s/conform ::hiccup))
;;=> {:name :h1}
It works like a charm. But can we cancel our correspondence?
(->> example
(s/conform ::hiccup)
(s/unform ::hiccup))
;;=> (:div)
Hmm, this must be a vector. Am I missing something? Let's see what the spec has to say about it.
(->> example
(s/conform ::hiccup)
(s/unform ::hiccup)
(s/explain ::hiccup))
;; val: (:div) fails spec: :user/hiccup predicate: vector?
;;=> nil
In fact, he fails. So the question is: how do I get this to work correctly?
source
share