2017-07-29 72 views

回答

3

從文檔字符串:

重新標記被生成期間使用 匹配的標籤重新標記生成的值。 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-specs/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)) 
+0

感謝您的偉大解釋和例子! – OlegTheCat