外国語論文講読III.
Object-Oriented Programming: the CLOS Perspective MIT Press, 1993.
以下で実装を行う。
(defclass standard-frame-class (standard-class)
((instances :reader instances :initform nil)))
(defmethod validate-superclass ((class standard-frame-class)
(super standard-class))
t)
(defclass standard-frame (relations-mv-mixin)
((name-of-frame :reader name-of-frame :iniarg :name-of-frame)
(part-of :initform nil :relation t :inverse parts)
(parts :initform nil :relation t :inverse part-of))
(:metaclass standard-frame-class))
mvはMultivalueのことである.
standard-frame は precedence listでstandard-object の前に挿入されるので、
そのために compute-class-precedence メソッドを書き換える。
(defmethod compute-class-precedence-list
((class standard-frame-class))
(let ((prec-list (call-next-method))
(std-frame-list (class-precedence-list
(find-class 'standard-frame))))
(append (remove-if '#(lambda (el)
(member el std-frame-list :test #'equal))
prec-list)
std-frame-list)))
このほか、以前出てきた short-term memory と long-term memory のために
ltm と stm という2つのクラスを定義しておく。
(defclass ltm () ()) (defclass stm (rms-mixin) ())こうしておくのは 'future extension'のためである。 ltmはstaticな情報を記録するが、stmは必要に応じてgarbage collectされてもよい。
(class line (imagedata)
start
end
length
(connected-with :relation t :inverse connected-with))
(instance l-1 line
(part-of 'cube)
(length 125))
instance マクロは make-instance を拡張して作られるが、
class マクロはどのmethodを拡張するのかに任意性があり、
(defmacro class (name supers &rest slots)
(let ((slotlist (preprocess-slots slots)))
`(ensure-class ',name
:direct-superclasses ',supers
:metaclass 'standard-frame-class
:direct-slots ',slotlist)))
だが、この方法だと渡されるオプションが標準と違っていたりすると
うまくいかないことが予想される.従って、MOPを用いてプロトコルを拡張する方向の
ほうが望ましい。
だが一方で、MOPを用いれば非常に柔軟で将来性の高い拡張が可能である。 このように目的に特化したクラスを作ることで、CLOS自身とユーザ拡張とを 区別することができ、扱いやすくなる. しかし、MOPの仕様がまだ固まっていないため、可搬性を重視するなら MOPを用いた拡張にはデメリットが大きい。
CLOSでは、ルールもオブジェクトとすることができる。 次のコード
(defrule test ruleset-1
(if (image parts ?part)
(?part size ?x)
(test (> ?size 100))
(?part color blue)
(assert (?part interpretation lake))
(print "found a lake"))
は適用される前に前処理され、ruleset-1 の中の test ルールオブジェクトとして
連結される. 中では、推論部、結論部がそれぞれのスロットに入る。これを示したのが
Fig.12.3である。ただし、これまで見てきたようにすべてオブジェクトにすると、オブジェクトの生成、 破壊や継承などにかかわるオーバーヘッドが大きくなる。 これを軽減するためには,動的に生成/破棄されるオブジェクトを最適化する オプティマイザが必要になってくるだろう。
後半では、総称関数の中で呼ばれる関数が中で独自の判断をするため、それを 後から制御できないという問題と、関数のprecedence orderを変えたいときの 問題などを言っている。(やや自明か?)
また、Metaobject Protocolの仕様がまだ定まっていないこと、 難しいためもっと構造化が必要であることなどがこれからの課題として指摘できる。