空想犬猫記

※当日記では、犬も猫も空想も扱っておりません。(旧・エト記)

Generic Method の呼び出し順序

について確認。

(defclass first () ())
(defclass second (first) ())
(defclass third (second) ())
(defmethod test :before (x y) (format t "0 0~%"))
(defmethod test :before (x (y first)) (format t "0 first~%"))
(defmethod test :before (x (y second)) (format t "0 second~%"))
(defmethod test :before ((x first) y) (format t "first 0~%"))
(defmethod test :before ((x first) (y first)) (format t "first first~%"))
(defmethod test :before ((x first) (y second)) (format t "first second~%"))
(defmethod test :before ((x second) y) (format t "second 0~%"))
(defmethod test :before ((x second) (y first)) (format t "second first~%"))
(defmethod test :before ((x second) (y second)) (format t "second second~%"))
(defmethod test ((x third) (y third)) (format t "third third~%"))
(test (make-instance 'third) (make-instance 'third))

before メソッドはmost specificからleast specificに呼び出されるとある。classの継承も左優先だったから,generic methodもより左の引数がspecificなほうが,よりspecificであるという順位づけになってるはず。そう思って既に実装しちゃったんだけど,実際にsbclで検証してみた。やるべきことの順序が逆だが,まあよかろう。

second second
second first
second 0
first second
first first
first 0
0 second
0 first
0 0
third third
T

うむ。思った通り。横が引数の並び,上方向の矢印をクラスの特殊化の順位だとすると,most specificからleast specificへは,ちょうど数字を数え上げての桁上がりさせるのと同じ原理で,インクリメントできる。メソッドの検索は,緑の玉の組み合わせを引数にして,次の緑の玉の組み合わせを作成するピンクの矢印の変換を関数化して,その結果を随時n分木へ入力するという方法でどうだろう。→ だめか。遅い。イテレータが上手にノードを渡り歩く方式なら大丈夫かな。何言ってるのか分からなくなってきた。眠い.寝よう。

これまでの実装は,実行前に呼び出す予定のメソッドリスト一覧を作成してから一気に実行してたんだけど,メソッドチェイン中に新しいメソッドが追加されたら…,というコメントを頂いて,generic method の呼び出しについてあれこれ考え直している。

追記:コメントを頂いて,メソッド呼び出し前にリスト一覧を作成する方法でよい模様。むしろ,メソッドチェイン実行中に定義されてメソッドをチェインに組み込む方が間違いであるとのこと。なるほど。(Lispの勉強と実装とを同時並行にする人がここにも‥笑)