我可以使用 Clojure 规范验证函数吗?
Can I validate functions with Clojure spec?
我可以使用 Clojure 规范系统来定义函数签名并验证函数是否满足它们吗?
以下是我尝试过但没有成功的一些例子
(s/valid? (s/fspec :args string? :ret string?) identity) ;; false
(def nope identity)
(s/valid? (s/fspec :args string? :ret string?) nope) ;; false
(s/conform (s/fspec :args string? :ret string?) identity) ;; invalid
(defn strmap [s] {:pre [(s/valid? string? s)] :post [(s/valid? string? %)]} s)
(s/valid? (s/fspec :args string? :ret string?) strmap) ;; false
(s/fdef strmap :args string? :ret string?)
(s/valid? strmap strmap) ;; true
(s/def ::str-pred (s/fspec :args string? :ret boolean?))
(s/valid ::str-pred (fn [s] true)) ;; false
我知道 fdef
,但我想要一些我可以创作的东西。例如,创建相关函数签名的映射。
clojure.spec
、malli
is a data-driven schema library that has support for function schemas
的替代方法
您可以使用 s/get-spec
访问函数的 :args
和 :ret
规范,然后验证:
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (defn strmap [s] s)
#'user/strmap
user=> (s/fdef strmap :args string? :ret string?)
user/strmap
user=> (s/valid? (:args (s/get-spec `strmap)) "foo")
true
user=> (s/valid? (:args (s/get-spec `strmap)) :bar)
false
我在 re-find.web 中使用它。
事实证明 spec 确实处理函数,但它期望参数是一个元组。
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) identity) ;; true!
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) (fn [x] (str x "hi there"))) ;; true
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) (fn [x] x)) ;; true
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) (fn [x] 42)) ;; false
匿名函数文字似乎确实存在一些问题。我可能对宏扩展有一些误解。
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) #(%)) ;; false
我可以使用 Clojure 规范系统来定义函数签名并验证函数是否满足它们吗?
以下是我尝试过但没有成功的一些例子
(s/valid? (s/fspec :args string? :ret string?) identity) ;; false
(def nope identity)
(s/valid? (s/fspec :args string? :ret string?) nope) ;; false
(s/conform (s/fspec :args string? :ret string?) identity) ;; invalid
(defn strmap [s] {:pre [(s/valid? string? s)] :post [(s/valid? string? %)]} s)
(s/valid? (s/fspec :args string? :ret string?) strmap) ;; false
(s/fdef strmap :args string? :ret string?)
(s/valid? strmap strmap) ;; true
(s/def ::str-pred (s/fspec :args string? :ret boolean?))
(s/valid ::str-pred (fn [s] true)) ;; false
我知道 fdef
,但我想要一些我可以创作的东西。例如,创建相关函数签名的映射。
clojure.spec
、malli
is a data-driven schema library that has support for function schemas
您可以使用 s/get-spec
访问函数的 :args
和 :ret
规范,然后验证:
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (defn strmap [s] s)
#'user/strmap
user=> (s/fdef strmap :args string? :ret string?)
user/strmap
user=> (s/valid? (:args (s/get-spec `strmap)) "foo")
true
user=> (s/valid? (:args (s/get-spec `strmap)) :bar)
false
我在 re-find.web 中使用它。
事实证明 spec 确实处理函数,但它期望参数是一个元组。
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) identity) ;; true!
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) (fn [x] (str x "hi there"))) ;; true
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) (fn [x] x)) ;; true
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) (fn [x] 42)) ;; false
匿名函数文字似乎确实存在一些问题。我可能对宏扩展有一些误解。
(s/valid? (s/fspec :args (s/cat :arg1 string?) :ret string?) #(%)) ;; false