1

単一のデータ型に対してマルチメソッドの複数の実装を作成するにはどうすればよいですか?

これは良い例ではないかもしれませんが、ネストされたベクトルを両方ともシーケンスとして扱うことができるという考えを示してくれることを願っています:

repl> (def thing [[[1] []] [27] [18 [32 35]]])

repl> (fmap count thing)
[2 1 2]

そしてツリーとして:

repl> (fmap (partial + 1) thing)
[[[2] []] [28] [19 [33 36]]]

同じ型に対して複数のマルチメソッド実装を作成して使用する一般的な方法は何ですか?

4

2 に答える 2

1

あなたの問題では、関数のタイプ(fmapの最初の引数)パラメーターでディスパッチする必要があります。私の知る限り、関数の引数の型を検出する (簡単な?) 方法はありません (間違っている場合は修正してください)。したがって、これをメタデータとしてパラメーターなどに追加する必要があります。例えば

(defmulti fmap (fn [f _] ((comp :arg-seq? meta) f)))

(defmethod fmap true [f col]
  (map-tree f col))

(defmethod fmap false [f col]
  (map f col))

(fmap (with-meta inc {:arg-seq? true}) thing)
-> [[[2] []] [28] [19 [33 36]]]

(fmap (with-meta count {:arg-seq? false}) thing)
-> (2 1 2)

しかし、これはあまり良くないようです。関数パラメーターのタイプを取得する他の方法がある場合、ソリューションはより見栄えがよくなります。

于 2012-12-14T17:50:03.293 に答える
0

マルチメソッドの考え方は、「異なる引数」に対して「同じ操作」を行うことです (異なる型である必要はありません)。「同じ引数」で「別の操作」を実行したい場合、マルチメソッドは適合しません.@DaoWenが示唆したように、別々の関数(または別々のマルチメソッド)を使用するだけがおそらく正しい方法ですそれについて行きます。

プログラムで引数を区別する何らかの方法があり、それらの特徴に基づいて異なるメソッド実装を使用することが概念的に理にかなっている場合は、defmultidispatch-fn引数を使用して区別することができます。

簡単な例として、キー :foo をディスパッチ fn として使用できます。これは、単一の引数としてマルチメソッドに渡されるマップ内のキー :foo に関連付けられた値に対してディスパッチを行います。

于 2012-12-14T17:41:22.363 に答える