2017-07-29 1 views

Répondre

3

De l'docstring:

retag est utilisé lors de la génération de valeurs générées avec retag balises correspondant. retag peut être soit un mot-clé, auquel la touche d'envoi sera associée, soit un fn de valeur générée et une étiquette d'envoi qui doit renvoyer une valeur de nouveau mise à jour.

Si retag est un mot-clé (comme dans le spec guide example), multi-spec crée en interne une fonction here qui est utilisé dans la fonction de mise en oeuvre du générateur. Par exemple, ces deux déclarations multiples spécifications sont fonctionnellement équivalentes:

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

Passer une retagfonction ne semble pas être une option très utile étant donné l'exemple du guide, mais est plus utile lors de l'utilisation multi-spec pour non Plans. Par exemple, si vous souhaitez utiliser multi-spec avec s/cat par exemple. aux spécifications arguments de fonction:

(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 prend deux ou trois arguments, selon la première arg. Si nous essayons de multi-spec naïvement en utilisant la, il ne fonctionnera pas mot-clé/tag 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 

C'est là être en mesure de passer une fonction retag est utile:

(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

Merci pour la grande explication et exemples! – OlegTheCat