22

defmulti と defmethod が使用される理由を知りたいですか? 利点は何ですか?そして、それをどのように使用しますか?コードで何が起こっているのか説明してください。

4

3 に答える 3

47

「一般的な用語」では、ステロイドの if/else と呼び、「感動」スタイルでは、「動的ディスパッチ」、「ランタイム ポリモーフィズム」などで名前を付けます。

Int の場合は数値を加算し、文字列の場合は文字列を連結するなど、さまざまなデータ型で機能する関数「Add」を定義するとします。if else を使用して実装するのは非常に簡単です。基本的には、引数のタイプを確認し、整数の場合はそれらを追加し、文字列の場合はそれらを連結し、それ以外の場合は例外をスローします。しかし、これの問題は、Add 関数に新しいデータ型のサポートを追加したい場合、Add 関数を変更する必要があることです。ケースはライブラリなどで定義されており、 defmultiこのdefmethod問題を解決できます。つまり、コードを変更せずに既存の関数に新しいケースを追加できます。

(defmulti add (fn [a b] [(type a) (type b)]))

add は関数名、無名関数は if/else です。基本的に、これは add 引数で呼び出され、この関数の戻り値が実装されているかどうかがチェックされます。それでは、Integer に実装してみましょう。

(defmethod add [Integer Integer] ([a b] (+ a b)))

[Integer Integer]で定義した無名関数の戻り値とdefmulti実装のソート スイッチ ケースです。

同様に、文字列に対してもできます

(defmethod add [String String] ([a b] (str a b)))

整数で呼び出す (add (int 1) (int 2))

文字列で呼び出す (add "hello" "world")

if/else に一致しないもの、つまりまだ実装されていないケースで呼び出すと、例外が発生します

于 2012-10-13T12:06:09.813 に答える
14

回答を読んだ後に(そして上記の例を使用して)私が観察したことから、次のことも理解に役立ちます。

コマンドを実行すると:

(add (int 5) (int 2))

「add defmulti」が実行され、リストが生成されます。

[Integer Integer]

それが生成されると、上記のリストで識別される「add defmethod」を探します。

(add [Integer Integer])

そして、受け取った引数を渡します。

引数の受け渡しを明確にするためにマルチメソッドを定義する別の方法は次のとおりです。

(defmulti add (fn [a b] [(type a) (type b)]))
(defmethod add [Integer Integer] [a b] (+ a b))
(defmethod add [String String] [a b] (str a b))

次に、関数を次のように実行します。

(add 12 73)

また

(add "thank" "you")
于 2012-10-13T13:47:09.830 に答える