clojure.spec.alpha
API有一个名为conformer
的宏,其描述如下:
用法:(conformer f) (conformer unf)接受一个语义为一致性的谓词函数,即它应该返回一个(可能转换的)值或:clojure.spec.alpha/无效,并返回一个将其用作谓词/构词器的规范。可选地获取第二个fn,该fn执行第一个结果的非形式。
如果不是深奥的话,我也不清楚。
它是用来干什么的?“未成形”(不应该是“非构词”)是用来做什么的?我打算从返回的“一致值”中重新创建原始数据?
更新
经过15分钟的实验,它似乎是从一个“谓词”创建一个新的“规范”(“规范”有什么特别的进展?)
我试过了
(require '[clojure.spec.alpha :as s :refer [valid? explain conform conformer]])
; ---
; Using purely clojure.spec.alpha:
; ---
(s/def ::vtx-x float?)
(s/def ::vtx-y float?)
(s/def ::vertex (s/keys :req [::vtx-x ::vtx-y]))
(type (s/get-spec ::vertex))
;=> clojure.spec.alpha$map_spec_impl$reify__1997
(conform ::vertex { ::vtx-x 1.0 ::vtx-y 2.0 })
;=> #:user{:vtx-x 1.0, :vtx-y 2.0}
(valid? ::vertex { ::vtx-x 1.0 ::vtx-y 2.0 })
;=> true
(conform ::vertex { ::vtx-x 1.0 })
;=> :clojure.spec.alpha/invalid
; ---
; Using my own special sauce predicate function, where the conformed
; value carries additional information ... maybe for a debugging system?
; ---
(defn my-vertex-conformer [v]
(when-let [ { x ::vtx-x y ::vtx-y } v ]
(if (and (float? x) (float? y))
[:comment "Vertex conforms!" :something (+ x y) :orig v]
; else
:clojure.spec.alpha/invalid)))
(defn my-vertex-unformer [conf-v] (get conf-v :orig))
(s/def ::my-vertex (conformer my-vertex-conformer my-vertex-unformer))
(type (s/get-spec ::my-vertex))
;=> clojure.spec.alpha$spec_impl$reify__2059
(conform ::my-vertex { ::vtx-x 1.0 ::vtx-y 2.0 })
;=> [:comment "Vertex conforms!" :something 3.0
;=> :orig #:user{:vtx-x 1.0, :vtx-y 2.0}]
(valid? ::my-vertex { ::vtx-x 1.0 ::vtx-y 2.0 })
;=> true
(conform ::my-vertex { ::vtx-x 1.0 })
;=> :clojure.spec.alpha/invalid
奖金,令人惊讶的是这里也不例外,这是疏忽吗?
(conformer map?)
;=> #object[clojure.spec.alpha$spec_impl$reify__2059 0x770b843 "clojure.spec.alpha$spec_impl$reify__2059@770b843"]
(type (conformer map?))
;=> clojure.spec.alpha$spec_impl$reify__2059
发布于 2019-09-12 03:20:37
它是用来干什么的?
用于创建一个规范,该规范(用于确定值时)可以返回与给定值不同的值。
(s/conform str 1)
=> 1 ;; (str 1) returned truthy value; input value unchanged
(s/conform (s/conformer str) 1)
=> "1" ;; returns (str 1)
“未成形”(不应该是“非构词”)是用来做什么的?我应该从返回的“一致值”中重新创建原始数据吗?
确切地说,unformer
函数可以使用s/unform
来逆转由构造器所做的任何更改。
(s/def ::str (s/conformer str #(Integer/parseInt %)))
(s/conform ::str 1)
=> "1"
(s/unform ::str "1")
=> 1
有机会简化示例规范:
(defn my-vertex-conformer [v]
(let [{x ::vtx-x y ::vtx-y} v] ;; don't need validation here
{:comment "Vertex conforms!" :something (+ x y) :orig v}))
(s/def ::my-vertex
(s/and ::vertex ;; because the validation is done by (s/and ::vertex ...)
(s/conformer my-vertex-conformer
:orig))) ;; keyword can be used as unform function
(->> {::vtx-x 1.0 ::vtx-y 2.0}
(s/conform ::my-vertex)
(s/unform ::my-vertex))
=> {::vtx-x 1.0 ::vtx-y 2.0}
奖金,令人惊讶的是这里也不例外,这是疏忽吗?
(conformer map?)
不,这里没有什么问题,尽管使用布尔谓词函数(如map?
和conformer
)可能是不寻常的
(s/conform (s/conformer map?) {})
=> true
(s/conform (s/conformer map?) [])
=> false
(s/conformer map?)
是一个使用任何值的规范,如果它是映射,则符合true,否则为false。
规范最初从何而来?
合同的概念已经有一段时间了,形式多种多样,例如https://docs.racket-lang.org/guide/contracts.html。也见contract。
https://stackoverflow.com/questions/57871705
复制