2017-07-29 2 views

答えて

3

再タグ付けは マッチングタグで生成された値を再タグ付けするために生成時に使用されます。 retagは、 ディスパッチタグが関連付けられるキー、または生成された値のfn、および適切にタグ付けされた値を返すべき ディスパッチタグのキーのいずれかです。

retag場合はmulti-specが内部発生実装関数で使用される関数hereを作成し、(spec guide exampleのように)キーワードです。例えば、これら2つのマルチ仕様宣言は、機能的に同等です:

retag 機能を渡す
(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)))) 

は、ガイドの例で与えられた非常に便利なオプションのように見えるが、非のため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は、最初の引数に応じて、2つのまたは3引数を取ります。我々は単純s/catキーワード/タグを使用してmulti-specにこれをしようとすると、それは動作しません。

(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

関連する問題