clojure spec,关键字应该是nilable

时间:2018-05-17 11:24:44

标签: clojure

我有一个简单的问题 鉴于规范def,我想使用相同的规范,但仅作为一个可变的变体。

E.g。

(s/def ::uuid uuid?)
(s/def ::problem-spec (s/keys :req-un [::uuid]))
(s/def ::nilable-problem-spec (s/keys :req-un [::uuid])) ; <- (or nil ::uuid)

; what I expect
(s/valid? ::uuid #uuid "9494a3e0-7ef0-4b3f-b539-bd7f7f4f0181") ; true
(s/valid? ::uuid nil) ; false
(s/valid? ::problem-spec {:uuid #uuid "9494a3e0-7ef0-4b3f-b539-bd7f7f4f0181"}) ; true
(s/valid? ::problem-spec {:uuid nil}) ; false
(s/valid? ::nilable-problem-spec {:uuid #uuid "9494a3e0-7ef0-4b3f-b539-bd7f7f4f0181"}) ; true
(s/valid? ::nilable-problem-spec {:uuid nil}) ; true

1 个答案:

答案 0 :(得分:2)

由于您已将::uuid定义为无法使用,因此您无法在地图/键集中使用::uuid键作为nilable值。这是有意的 - 规范中的合格密钥是全局定义的。

在这种情况下,您可以将::uuid规范为nillable,然后限制密钥集的非可终止版本:

(s/def ::uuid (s/nilable uuid?))

(s/def ::problem-spec (s/and (s/keys :req-un [::uuid])
                             #(some? (:uuid %))))

(s/def ::nilable-problem-spec (s/keys :req-un [::uuid])) ;; as previously

或者,由于您在地图中处理非限定键,因此您还可以定义两个具有不同语义的不同限定uuid关键字:

(s/def :nillable/uuid (s/nilable uuid?))
(s/def :non.nil/uuid uuid?)

(s/def ::problem-spec (s/keys :req-un [:non.nil/uuid])))
(s/def ::nilable-problem-spec (s/keys :req-un [:nillable/uuid]))