多重ディスパッチ(マルチメソッド)について
でも最初は「すげー」と思ったけどどういうときに役に立つんだろう。すべての基底クラス的なオブジェクトがあれば(仮にObjとする)、(defmethod method((x Obj) (y Foo) ...)で「レシーバが何かにかかわらず引数yがFooなら同じ処理」ってのができるわけなのだけど、それってFooのメソッドにすべきな気がするし。
たとえば、Wikipediaの例なんてどうでしょ。多重ディスパッチ - Wikipedia
あと、CLOS系の多重ディスパッチの嬉しいところは、実行時に型をみてディスパッチしてくれるところらしいす。実際に使ったことない、というかHaskell Hackathonで使おうとして時間切れになった。細かい議論は下記のLingrのログがくわしい。
http://www.lingr.com/room/parsing/archives/2007/11/07#msg-17832175
たとえば、Fooというクラスを継承した2つのクラスBarがあるとして、次のようなJavaっぽい疑似コードをかんがえる。
void hoge(Foo foo){ println("Foo!"); } // hoge1 void hoge(Bar bar){ println("Bar!"); } // hoge2 ... Bar bar_bar = new Bar(); Foo foo_bar = new Bar(); hoge(bar_bar); // hoge2がよばれる hoge(foo_bar); // hoge1がよばれる
Javaの場合、コンパイル時に型をみてディスパッチするので、hoge(foo_bar)はhoge1が呼びだされる。しかし、foo_barの中身は実行時にはBarのインスタンスなのだから、hoge2がよびだされるとうれしい。CLOSの多重ディスパッチの場合、そもそも型宣言がないので実行時にオブジェクトを見て、ディスパッチする先を決めてくれるから、hoge2に相当するメソッドを呼びだせる、らしい(入れ知恵)。
実際に役立つ場面としては、構文木をあつかうときとかですかね。Cとかだと、typeとかいうメンバを構造体にもたせて、それをswitchなんてことをしたりするけど、CLOSではそのtypeの情報をクラス自身に持たせることができる。Exprというクラスを継承する OperatorExpr, FuncallExpr とかがあって、それぞれに対してメソッドを定義しておけばswitchを長々とかかなくてもよい。
なんかすごい適当な知識で適当にかいたので、つっこみ希望。