【发布时间】:2019-09-10 13:18:00
【问题描述】:
clojure.spec.alpha API 有一个名为 conformer 的宏,其描述如下:
Usage: (conformer f) (conformer f unf) takes a predicate function with the semantics of conform i.e. it should return either a (possibly converted) value or :clojure.spec.alpha/invalid, and returns a spec that uses it as a predicate/conformer. Optionally takes a second fn that does unform of result of first
这对我来说不清楚,如果不是深奥的话。
它是做什么用的? “unformer”(不应该是“unformer”)是用来做什么的?我想从返回的“符合值”重新创建原始数据?
更新
经过 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
【问题讨论】:
-
我真的很喜欢这个规范,显然它也转移到了 Elixir:github.com/vic/spec - 它最初来自哪里?
标签: clojure clojure.spec