集合

你可以通過多種方式對集合進行規範。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