Czy możesz wyjaśnić na przykładach, w jaki sposób parametr retag
wpływa na tworzenie ? Uważam, że dokumentacja multi-spec
jest trudna do strawienia.Co oznacza parametr retag w s/multi-spec?
Odpowiedz
Z docstring:
zmieniać tagów jest używany podczas generowania zmieniać tagów wygenerowane wartości z pasujące do tagów. retag może być słowem kluczowym, przy którym klucz zostanie przypisany znacznikiem ekspedycyjnym lub fn wygenerowanej wartości i znacznikiem ekspedycyjnym , który powinien zwrócić odpowiednio zmienioną wartość.
Jeśli retag
to słowo kluczowe (jak w spec guide example) multi-spec
wewnętrznie tworzy funkcję here, który jest wykorzystywany w funkcji implementacji generatora. Na przykład, te dwie zgłoszeń wielo-spec są funkcjonalnie równoważne:
(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))))
Przekazanie retag
funkcji nie wydaje się być bardzo przydatna opcja podanym przykładzie przewodnika, ale jest bardziej przydatne przy multi-spec
za nieprzestrzeganie mapy. Na przykład, jeśli chcesz użyć multi-spec
z s/cat
np. spec argumenty funkcyjne:
(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
trwa dwa lub trzy argumenty, w zależności od pierwszego Arg. Jeśli staramy się multi-spec
to naiwnie pomocą s/cat
kluczowym/tag, to nie będzie działać:
(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
To gdzie jest w stanie przekazać retag
funkcja jest użyteczna:
(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))
Dziękuję za wielki wyjaśnienie i przykłady! – OlegTheCat