gpt4 book ai didi

Clojure 规范 "conformer"函数,它是什么?

转载 作者:行者123 更新时间:2023-12-05 03:58:33 26 4
gpt4 key购买 nike

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”(不应该是“unconformer”)是干什么用的?我想从返回的“一致值”中重新创建原始数据?

更新

经过15分钟的实验,似乎是要从一个“predicate”创建一个新的“spec”(这个“spec”有什么特别之处??)

我试过了

(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

奖金,令人惊讶的是这里也不异常(exception),这是疏忽吗?

(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

最佳答案

What is it used for?

用于创建规范(当用于符合值时)可以返回与给定值不同的值。

(s/conform str 1)
=> 1 ;; (str 1) returned truthy value; input value unchanged
(s/conform (s/conformer str) 1)
=> "1" ;; returns (str 1)

What is the "unformer" (shouldn't that be an "unconformer") used for? I suppose to recreate the original data from the returned "conformed value"?

确切地说,unformer 函数可用于反转使用s/unform 的conformer 所做的任何更改。

(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}

Bonus, amazingly no exception here, is this an oversight?

(conformer map?)

不,这里没有任何问题,尽管将 map? 之类的 bool 谓词函数与 conformer 一起使用可能很不寻常:

(s/conform (s/conformer map?) {})
=> true
(s/conform (s/conformer map?) [])
=> false

(s/conformer map?) 是一个规范,它可以接受任何值并且如果它是一个映射则符合 true,否则为 false。

where does [spec] come from initially?

契约(Contract)的概念已经以各种形式出现了一段时间,例如https://docs.racket-lang.org/guide/contracts.html .另见 https://en.wikipedia.org/wiki/Design_by_contract .

关于Clojure 规范 "conformer"函数,它是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57871705/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com