指定一个集合,使其恰好具有每个值之一
Spec a collection to have exactly one of each values
有这张地图:
{:id 5
:fields [{:field :a :val 1}
{:field :c :val 3}
{:field :b :val 2}
{:field :d :val 4}
...]}
和每个字段值的单独规范,如 (s/def ::field-a ...)
、(s/def ::field-b ...)
、(s/def ::field-c ...)
、
我应该如何指定它以便地图中的 :fields
包含 {:field a ...}
、{:field b ...}
、{:field c ...}
(无视顺序)和可选其他值?
是的,我知道它有点冗长,但无论如何:
(s/def ::id int?)
(s/def ::val int?)
(s/def ::field keyword?)
(s/def ::some string?)
(s/def ::abstract-field (s/keys :req-un [::field ::val]))
(s/def ::field-a (s/and (s/keys :req-un [::field ::val]) #(= (:field %) :a)))
(s/def ::field-b (s/and (s/keys :req-un [::field ::val]) #(= (:field %) :b)))
(s/def ::field-c (s/and (s/keys :req-un [::field ::val]) #(= (:field %) :c)))
(s/def ::field-d (s/and (s/keys :req-un [::field ::val]) #(= (:field %) :d)))
(s/def ::fields (s/and
(s/+ (s/alt :required (s/or :a ::field-a
:b ::field-b
:c ::field-c
:d ::field-d)
:rest ::abstract-field))
(fn [x] (= [:a :b :c :d]
(into [] (sort (map (comp first second) (filter #(= :required (first %)) x))))))))
(let [x1 [{:field :b :val 2}
{:field :a :val 1}
;{:field :a :val 1}
{:field :d :val 4}
{:field :e :val 4}
{:field :c :val 3}
]]
(s/explain ::fields x1)
(s/conform ::fields x1))
有这张地图:
{:id 5
:fields [{:field :a :val 1}
{:field :c :val 3}
{:field :b :val 2}
{:field :d :val 4}
...]}
和每个字段值的单独规范,如 (s/def ::field-a ...)
、(s/def ::field-b ...)
、(s/def ::field-c ...)
、
我应该如何指定它以便地图中的 :fields
包含 {:field a ...}
、{:field b ...}
、{:field c ...}
(无视顺序)和可选其他值?
是的,我知道它有点冗长,但无论如何:
(s/def ::id int?)
(s/def ::val int?)
(s/def ::field keyword?)
(s/def ::some string?)
(s/def ::abstract-field (s/keys :req-un [::field ::val]))
(s/def ::field-a (s/and (s/keys :req-un [::field ::val]) #(= (:field %) :a)))
(s/def ::field-b (s/and (s/keys :req-un [::field ::val]) #(= (:field %) :b)))
(s/def ::field-c (s/and (s/keys :req-un [::field ::val]) #(= (:field %) :c)))
(s/def ::field-d (s/and (s/keys :req-un [::field ::val]) #(= (:field %) :d)))
(s/def ::fields (s/and
(s/+ (s/alt :required (s/or :a ::field-a
:b ::field-b
:c ::field-c
:d ::field-d)
:rest ::abstract-field))
(fn [x] (= [:a :b :c :d]
(into [] (sort (map (comp first second) (filter #(= :required (first %)) x))))))))
(let [x1 [{:field :b :val 2}
{:field :a :val 1}
;{:field :a :val 1}
{:field :d :val 4}
{:field :e :val 4}
{:field :c :val 3}
]]
(s/explain ::fields x1)
(s/conform ::fields x1))