5
你能用例子来解释retag
参数如何影响multi-spec
创建?我发现multi-spec
文档很难消化。s/multi-spec中的retag参数是什么意思?
你能用例子来解释retag
参数如何影响multi-spec
创建?我发现multi-spec
文档很难消化。s/multi-spec中的retag参数是什么意思?
从文档字符串:
重新标记被生成期间使用 匹配的标签重新标记生成的值。 retag可以是关键字,关键字是 调度标签将被关联,或者生成值fn和 调度标签,该标签应该返回适当的重新标记的值。
如果retag
是一个关键字(如在spec guide example),multi-spec
内部创建其在发电机执行功能中使用的功能here。例如,这两个多规格的声明在功能上等同:
(s/def :event/event (s/multi-spec event-type :event/type))
(s/def :event/event (s/multi-spec event-type
(fn [genv tag]
(assoc genv :event/type tag))))
传递一个retag
功能似乎并不像给导游的例子一个非常有用的选项,但使用multi-spec
用于非时是比较有用地图。例如,如果您想要使用multi-spec
和s/cat
符合规范函数参数:
(defmulti foo first)
(defmethod foo :so/one [_]
(s/cat :typ #{:so/one} :num number?))
(defmethod foo :so/range [_]
(s/cat :typ #{:so/range} :lo number? :hi number?))
foo
需要两个或三个参数,根据第一ARG。如果我们试图multi-spec
这个天真地使用s/cat
关键字/标签,它不会工作:
(s/def :so/foo (s/multi-spec foo :typ))
(sgen/sample (s/gen :so/foo))
;; ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.Associative
这是能够传递一个retag
函数,其中很有用:
(s/def :so/foo (s/multi-spec foo (fn [genv _tag] genv)))
(sgen/sample (s/gen :so/foo))
;=>
;((:so/one -0.5)
; (:so/one -0.5)
; (:so/range -1 -2.0)
; (:so/one -1)
; (:so/one 2.0)
; (:so/range 1.875 -4)
; (:so/one -1)
; (:so/one 2.0)
; (:so/range 0 3)
; (:so/one 0.8125))
感谢您的伟大解释和例子! – OlegTheCat