#:g1: Metaobject Protocol及び関連技術についての個人的まとめ

Posted 2021-09-04 06:37:35 GMT

個人的にはMetaobject Protocol(MOP)という技術は好きなのですが、壮大な機構として捉えられがちな割には応用が大したものでもなかったりする印象を持ちます。
今回は、その辺の個人的考えをまとめてみたいと思います。

MOPという技術の大枠(壮大)

個人的には、LispのMOPは、Lispのインタプリタ(eval)をオブジェクト指向プログラミング的に展開したもの、と最近は考えています。

CLOSとそのMOPの初期の頃の文献を参照するとProceedings of the First CLOS Users and Implementors Workshop 1988の中のThe Importance of Being Metaで、Lispらしいオブジェクト指向プログラミングシステムの探求のようなことが書かれています。骨子は、

というところですが、どうやら当時のXerox近辺では、CLOSという用語をCommon Lispの方言の一つ(=別言語)という機微で使っているように思えます。
説明の都合上かもしれませんがこの文脈での、Common Lispという用語はCLtL1=Common Lisp 1984=これまでのLispの代表、のような機微を感じます。
ちなみに、オブジェクト指向プログラミングの本を読んでいると、CLOSという言語が独立して存在するかのような記述が散見されますが、1990年代前半のXerox近辺の活動の影響なのかと思わなくもありません(もしくはLispベンダーのマーケティングか)

閑話休題。さて、Lispらしさを追求するというCLOSは、FlavorsやLOOPSと何が違うのか、ということになりますが、その違いがMOPになります。
FlavorsやLOOPSは、既存のLisp処理系の上に構築したDSL/アドオンという形態ですが、MOPはLisp本来の力を引き出すという主張があり、CLOSは極端に説明すると、メタオブジェクトで構成されたインタプリタ(eval)を核とする新しいLisp方言という方向性だったのではないかと思います。

古典的なLispでは、eval万能関数が、データを処理していきますが、このevalにオブジェクト指向技術を適用するというイメージかと想像しています。

面白いのは、Smalltalk誕生のきっかけになったLispからの影響としてアラン・ケイは、全体をfexpr化したevalというのを挙げています。

Smalltalkの歴史のII. 1967-69—The FLEX Machine, a first attempt at an OOP-based personal computerあたりで述べられていますが、evalが関数(引数を評価した後手続き処理する)と特殊形式/fexpr(手続きが引数の評価も担当する)に分けているところを全面的にfexpr化することを考えた結果、オブジェクトが渡されたメッセージをオブジェクト自身が評価する→メッセージ送信を核とするオブジェクト指向、という風に概念が整理されたようです。そういう意味では、MOPはオブジェクト指向プログラミングシステムとしても原点回帰だったのではないでしょうか。

MOPと関連技術(大き目な流れ)

Open Implementation(OI)

Kiczales先生は後にMOPの仕事をLisp以外にも応用するという流れで、1990年代中半あたりまで、Open Implementationという技術を追求します。
これはMOPで展開されたようなメタオブジェクトでプロトコル化されたアプローチをLisp以外のメジャーなコンパイラ言語などにも適用するというものだったと思いますが、後のアスペクト指向プログラミングのようにブームになるようなことはなかったようです。

アスペクト指向プログラミング(AOP)

Kiczales先生は、1990年代中半以降、OIからAOPに研究主軸を移しますが、この辺りの連続性は私は詳しく追えていません。
OIや、MOP技術の応用事例として、プログラミングにまつわる横断的な問題をアスペクトとして切り出し対処するのがAOPなのか、はたまた逆なのか、似ているけれど根本は違うのか。
また、AOPとリフレクション技術も一緒に語られることが多いと思いますが、これは、メジャーな言語の多くはLisp等のevalな背景を持つ言語とは違い、プログラミング→コンパイル→実行、というバッチ指向であり、実行→コンパイル→プログラミングという遡り操作の実現が殊更難しいために技術的挑戦/研究が発展することになったのかと思います。

柔軟な言語をいかに速くするかと、速い言語をいかに柔軟にするかは、大体似たような技術になるのかとは思いますが、柔軟な言語の利用者からすると何故そのような技術が必要とされるのかの動機の理解が難しいことも多い気がします。

Lispは手続きの実行に柔軟にフックを掛けることが可能なのですが、アドバイス機構やマクロでAOPを真似ることができることをもって「Common LispはAOPが実現できている」という人もいます。しかし、個々のフックをアスペクトという視点で切り出して操作するようなフレームワークも存在しませんし、飽く迄AOPのようなことも個別に記述すれば可能、程度のことかと思うのでAOPをサポートしているとはいいがたいと思います。

MOPとオブジェクト指向システム(中くらい)

Lispらしさを追求し、Flavorsのようなアドオンではない、という当初のCLOSでしたが、結局のところANSI Common LispではMOPが規格に入らなかったため、Common Lispのオブジェクト指向システムは既存のFlavorsのようなアドオンと大差ないものとなりました。

とはいえ、MOPありで規格化されたとしても、急進的にevalにまでMOPが適用されるということもなかったと思います。
結果的にはANSI Common Lisp+MOPでは、データ定義/操作の側と手続き呼び出しの操の系統の二系統がevalの外側にユーザー拡張機能として装着されていて、それより外側でカスタマイズができる、という風になっています。

総称関数が関数呼び出しの機構に若干食い込んではいますが、MOP全面的に適用されていれば、また違った形態になったでしょうし、evalや、compileがMOP化されていれば、コンパイラの最適化等もユーザーが柔軟にカスタマイズ可能になったと思われます。
このような形態が恐らくOpen Implementation化されたCommon Lispだったのかと推測します。恐らくOI化されたCLではAOPを組込むのもさらに容易であったでしょう。

メタクラスのカスタマイズ(小さい流れ)

さてMOPの応用事例として、データ生成にまつわる一連の流れのカスタマイズと、手続き呼び出しのカスタマイズがあります。 これらは、データ生成をするデータ(メタオブジェクト)を操作する手続きの一連の規約(Metaobject Protocol)のカスタマイズとして操作しますが、基本的には一連のデータ操作においてフックできるポイントがあり、このフックをOOP的に拡張することによりカスタマイズができる、というところになります。

MOPの応用にも、大き目のものから小さ目のものまでありますが、大きいものから順に列挙してみましょう。

MOPでオブジェクト指向システムや類似のシステムを構築する

1980年代のLispの需要として、エキスパートシステムの構築の核言語というものがありました、ミンスキー先生のフレーム理論のシステムをLisp上に構築するようなことは多く行なわれていましたが、フレームシステムはオブジェクト指向システムと非常に似たところがありこれらを構築するのにCLOSの機能はよく活用されています。ただ、Flavors等でも似たようなことは実現されていましたので、より柔軟にアプローチできるようになった、程度でしょうか。
一応MOPサポートの強みとしては、それ自身が柔軟に変更可能であるため、基盤となるオブジェクト指向システムから乖離しているような機構でも差分を吸収できるというのはあると思います。

実際、オブジェクト指向システムをCommon Lisp+MOPで構築したという例では、CommonObjectsやObject LISPが古くから知られており、MOPの柔軟性の証左ともされています。

また、セマンティックウェブのOWL処理系をCommon Lisp上に構築したSWCLOSのようなものもあります。

ほか参照

入出力のフック

メタクラスの応用としては最も古くから存在し典型的なものとしてオブジェクトの永続化があります。
エキスパートシステムで利用するフレームのデータを格納する手段として出発し発展してきましたが、大抵は永続化用のメタクラスを定義し、ユーザーはそれを意識することなしにシステムが勝手に永続化しているようなシステムの実現に使われます。

古くは、HPのPCLOS(1988)からありますが、最近のAllegro CLのように処理系と統合されていることもあります。

また、RDBとオブジェクト指向システムを透過的に接続するORMも類似の技術ですが、こちらの実現にも良く使われています。

雑多なフックや挙動のカスタマイズ

雑多なフックや挙動のカスタマイズは多数ありますが、Common Lisp自体の柔軟性が高いためMOPを使わなくとも別の手段で実現できてしまうことが殆どです。

等々、細かいカスタマイズは沢山ありますが、当然ながら、MOPはオブジェクト指向システム固有の操作に近い部分のカスタマイズを得意としているかと思います。

まとめ

以上、長々と書いてきましたが、まとめると現在のANSI Common Lisp+MOPで可能な応用で最大のものは、オブジェクト指向システムやフレームシステムのCommon Lisp上での実現、最小のものはオブジェクト生成にまつわるちょっとしたフック、あたりになると思います。

究極形態としては、Open Implementation化されたCommon Lispだったと思うのですが、そういうCommon Lisp処理系がいつの日か登場すると面白いなと思います。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus