Clojure 规范:在 "coll-of" 中使用 "spec" 而不是 "pred" 确实有效。这个可以吗?

Clojure spec: Using a "spec" instead of a "pred" in "coll-of" actually works. Is this ok?

我正在尝试 Clojure spec 并从函数 :pre 约束中调用它。

我的规范 ::mustbe-seql-of-vec-of-2-int 将检查传递给函数的参数是否是从 0 到 4 个恰好 2 个整数的向量的序列:

(require '[clojure.spec.alpha :as s])

(s/def ::mustbe-seql-of-vec-of-2-int
   (s/and 
      ::justprint
      (s/coll-of 
         ::mustbe-vec-of-2-int 
         :kind sequential?
         :min-count 0
         :max-count 4)))

因此规范由其他规范组成,特别是 ::justprint 除了打印传递的参数以进行调试和 coll-of 之外什么都不做,以测试集合参数。

coll-of 的文档说:

Usage: (coll-of pred & opts)

Returns a spec for a collection of items satisfying pred. Unlike 'every', coll-of will exhaustively conform every value.

但是,作为第一个参数,我没有使用 pred(一个接受要检查的参数并返回真值的函数),而是另一个规范(一个接受要检查的参数并返回的函数)不确定是什么),在这种情况下,规范在 ::mustbe-vec-of-2-int.

下注册

这非常有效。

这种风格是否正确并且有望奏效?

P.S.

(s/def ::justprint
   #(do 
      ; "vec" to realize the LazySeq, which is not realized by join
      (print (d/join [ "::justprint ▶ " (vec %) "\n"] ))      
      true))

(s/def ::mustbe-vec-of-2-int
   (s/coll-of integer? :kind vector? :count 2))

Is this correct style and expected to work?

是的。规范、可以解析为规范的关键字和普通谓词函数可以在 clojure.spec API 的许多部分互换使用。 "Pred" 在该文档字符串的上下文中比一般的 Clojure 谓词函数具有更广泛的含义,例如nil?.

(require '[clojure.spec.alpha :as s])

(s/conform int? 1) ;; => 1
(s/conform int? false) ;; => :clojure.spec.alpha/invalid

s/def 修改 clojure.spec 注册表,将关键字与规范值相关联。当您将 ::some-spec-keyword 传递给 clojure.spec API 时,它会从注册表中自行解析规范值。您还可以 "alias" 规格,例如(s/def ::foo ::bar).

(s/def ::even-int? (s/and int? even?))
(s/conform ::even-int? 2) ;; => 2
(s/conform ::even-int? 3) ;; => :clojure.spec.alpha/invalid

所以这些都是等价的:

(s/conform (s/coll-of (s/and int? even?)) [2 4 6 8])
(s/conform (s/coll-of ::even-int?) [2 4 6 8])
(s/def ::coll-of-even-ints? (s/coll-of ::even-int?))
(s/conform ::coll-of-even-ints? [2 4 6 8])