集合

你可以通过多种方式对集合进行规范。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