集合
你可以通过多种方式对集合进行规范。coll-of 允许你指定集合并提供一些额外的约束。这是一个简单的例子:
(clojure.spec/valid? (clojure.spec/coll-of int?) [1 2 3])
;; => true
(clojure.spec/valid? (clojure.spec/coll-of int?) '(1 2 3))
;; => true
约束选项遵循集合的主要规范/谓词。你可以使用:kind
约束集合类型,如下所示:
(clojure.spec/valid? (clojure.spec/coll-of int? :kind vector?) [1 2 3])
;; => true
(clojure.spec/valid? (clojure.spec/coll-of int? :kind vector?) '(1 2 3))
;; => false
以上是错误的,因为传入的集合不是向量。
(clojure.spec/valid? (clojure.spec/coll-of int? :kind list?) '(1 2 3))
;; => true
(clojure.spec/valid? (clojure.spec/coll-of int? :kind set?) #{1 2 3})
;; => true
(clojure.spec/valid? (clojure.spec/coll-of int? :kind set?) #{1 "2" 3})
;; => false
以上是错误的,因为并非集合中的所有元素都是整数。
你还可以通过以下几种方式约束集合的大小:
(clojure.spec/valid? (clojure.spec/coll-of int? :kind vector? :count 3) [1 2 3])
;; => true
(clojure.spec/valid? (clojure.spec/coll-of int? :kind vector? :count 3) [1 2])
;; => false
(clojure.spec/valid? (clojure.spec/coll-of int? :min-count 3 :max-count 5) [1 2 3])
;; => true
(clojure.spec/valid? (clojure.spec/coll-of int? :min-count 3 :max-count 5) [1 2])
;; => false
你还可以使用:distinct
强制集合中元素的唯一性:
(clojure.spec/valid? (clojure.spec/coll-of int? :distinct true) [1 2])
;; => true
(clojure.spec/valid? (clojure.spec/coll-of int? :distinct true) [2 2])
;; => false
coll-of
确保检查序列中的所有元素。对于大型集合,这可能效率非常低。every
的行为与 coll-of
一样,只是它只对相对较少数量的序列元素进行采样以保证一致性。这适用于大型集合。这是一个例子:
(clojure.spec/valid? (clojure.spec/every int? :distinct true) [1 2 3 4 5])
;; => true
map-of
类似于 coll-of
,但是对于地图。由于地图同时具有键和值,因此你必须同时提供键的规范和值的规范:
(clojure.spec/valid? (clojure.spec/map-of keyword? string?) {:red "red" :green "green"})
;; => true
与 coll-of
一样,map-of
检查所有地图键/值的一致性。对于大型地图,这将是低效的。与 coll-of
一样,map-of
提供 every-kv
,用于从大型地图中有效地采样相对较少的值:
(clojure.spec/valid? (clojure.spec/every-kv keyword? string?) {:red "red" :green "green"})
;; => true