如何解决我可以使用 Clojure 规范验证函数吗?
我可以使用 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
,但我想要一些我可以创作的东西。例如,创建相关函数签名的映射。
解决方法
您可以使用 :args
访问函数的 :ret
和 s/get-spec
规范,然后进行验证:
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 中使用它。
,事实证明规范确实处理函数,但它期望参数是一个元组。
id=31
匿名函数文字似乎存在一些问题。我可能对宏扩展有些误解。
(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
,
clojure.spec
的替代方案,malli
是一个数据驱动的架构库,它具有 support for function schemas
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。