コンテクスト
私は最近、マルチメソッドとプロトコルを含む多くのコードを書いています。
私のマルチメソッドのほとんどはシングルディスパッチであることがわかりました-それらは引数の1つのタイプにのみ依存します。
これらは、代わりにプロトコルにフィールドを追加することで、マルチメソッドを実際に置き換えることができる状況です。
質問
マルチメソッドを代わりにプロトコルに置き換えることができる状況では、プロトコルの代わりにマルチメソッドを使用する理由はありますか?
ありがとう!
私は最近、マルチメソッドとプロトコルを含む多くのコードを書いています。
私のマルチメソッドのほとんどはシングルディスパッチであることがわかりました-それらは引数の1つのタイプにのみ依存します。
これらは、代わりにプロトコルにフィールドを追加することで、マルチメソッドを実際に置き換えることができる状況です。
マルチメソッドを代わりにプロトコルに置き換えることができる状況では、プロトコルの代わりにマルチメソッドを使用する理由はありますか?
ありがとう!
個人的には、プロトコルよりも効果的に表現を動作から切り離すマルチメソッドを好みます。パフォーマンスとは別に、プレーンマップを使用してデータを表現したり、必要に応じて複数のディスパッチを追加したり、「物理」タイプ以外のプロパティにディスパッチしたりするオプションを犠牲にする理由はほとんどありません(これ自体は一般的に優れた概念ではありません私の意見では、頼りにしています)。
要件が変更される合理的な可能性があり、将来的に複数のディスパッチを活用する必要がある場合は、マルチメソッドの使用を選択できます。
それ以外の場合は、目的に十分である場合にプロトコルを優先する必要があります。
私は通常、プロトコルを好みます。それらはより優れたパフォーマンスを提供し、一般的なケース (タイプの単一ディスパッチ) を非常にうまく処理します。
場合によっては、より洗練されたディスパッチが本当に必要になることがあります。その場合は、次のいずれかを実行できます。
(cond .....)
ディスパッチを処理する短いカスタム コード (通常は) を記述します。たとえば、マルチメソッドは値の範囲をうまく処理できないため、これはマルチメソッドよりも優れている場合があります。役に立つ追加のアドバイスは、適切なプロトコル関数に委譲する方法でメインの (公開されている) 関数を作成することです。
たとえば、次のようになります。
(defn my-api-function [a b]
"Do interesting things with a and b"
(multimethod-function
(protocol-function a)
(protocol-function b)))
これにより、大規模なリファクタリングや呼び出しコードへの影響を必要とせずに、後で内部実装を変更するための十分な柔軟性が得られます。