昨日、昼食にカリブまでドライブ。広島呉道路に入って、坂インターを降りる。呉方面、FINDS付近まで走る。ないねえ。ちゃんと地図を調べてくればよかったのに。聞いた話を元に、呉ポートピアに入って方向転換すると戻る。坂インターの出口を通り過ぎて、左側、ダイキのある道に入って海際まで走ったり、うろうろ。
話に聞いたとおり、ダイキ側から海沿いに行けないことはない。実際そうするはめになったのだが。広島大橋から坂北を降りて、右折してすぐの坂横浜(広島にも横浜港があるらしい)のT字交差点を右折するのが正解。案内が出ている。わかっていないと見落とす。そこから黄色の中央線を辿ってずーっと走って、最後にやはり右折して峠に上がって降りると大体近くに来ている。案内が出ているので指示に従って左折。もうわかるよね。
カリブのレストラン知る人ぞ知る有名な店らしいが、土日は音楽の時間に合わせていくとよいのかもしれない。土曜日の昼を少し回っていたが、まだ空いていて、当日は予約なしで問題なく入れた。音楽の時間などは予約しておいた方が安心だろう。
対岸に見える山は黄金山。南岸道路(広島高速3号線)が走っている。
正面には右手から広島市内黄金山から宇品方面の南岸が、左手には金輪島が見えている。→ [Google Maps]
TSNETで、Larry Wallがどこで最初にPerlは「ポストモダンのプログラミング言語だ」と言ったかが話題となった。
オライリーのperl.comにあるPerl, the first postmodern computer languageの記事(Larry Wall,March 09, 1999)には、「The following is the text of Larry Wall's talk at Linux World on Wednesday, March 3.」と書かれていて、それが正解である。実は、Mooseモジュールのドキュメントにもそのことが記載されているので翻訳してみよう。
待って、ポストモダン、私はちょうどモダンだと思ったのだが?
つまり、私はLarry Wallの「Perl, the first postmodern computer language」と題した1999年のLinux Worldのトークを読んだのだ。そこで、彼は、彼が如何にクールと考えるが故にPerlのための機能(features)を取り上げ、価値がないと考えるものを捨てたかについて話した。これは、我々がMooseで如何に同じことをしたかについて考えさせた。Mooseのために、Perl 6、CLOS(LISP)、Smalltalk、Java、BETA、Ocaml、Rubyなどから機能を「拝借」した。そして、我々が好きでない(価値がない理由)部分をポイと投げ捨てた。つまり、この理由によって(そして二、三の他の理由で)、私は再び、Mooseをポストモダンオブジェクトシステムと呼んだ。
もう十分。
Larry WallはPostmodernだけでなく、哲学や歴史にもかなり詳しい。少し勉強して読まないと歯が立たないかも。Larry Wallのトークは1999年で、1997年のソーカル事件(「知」の欺瞞)を受けた話だろうと思われる。しかし、僕らはLWを含めて1970年代にPostmodernの元となる構造主義を知っていた年代なのだ。もっとも当時今理解している程度のレベルにあったとは言い難い。ファッションに過ぎなかったかもしれない。Larryはthe Modern periodは間違えた名前付けだと言う。モダンの概念は現在(now)や新しい(new)概念を常に連想するからだ。そうするとポストモダンは未来を指すべきだというのが本記事のタイトルである。日本語では、「近代」と「現代」という用語を使い分けているが、英語にはmodernしかない。しかし、歴史が進行するにつれて、近代も近代でなくなり、現代も現代でなくなるから、結局同じ矛盾を孕むようになるわけだが・・・そのうち、人間は古典主義時代以降の近代に新しい名前を考え出すだろう。現代との区分をどこにするかはまだ定かでない。
ポストモダンについては今後取り上げる機会もあるので、とりあえず放り投げておいて^^;)、BUILDING CLASSES WITH MOOSEの項を訳しておこう。
Mooseでクラスを構築する
Mooseはクラス構築/定義に、できるだけ多くの便利さをもたらすようにあらゆる試みを行うが、あなたが欲するなら、あなたの方法の外に止まる。ここにMooseでクラスを構築する時、注目すべき二、三の項目がある。
extendsで特定されないならば、Mooseを使うあらゆるクラスは、Moose::Objectから継承する。
Mooseは継承する属性を含めすべての属性をhasで定義して管理する。そして、Moose::Objectから継承するnewを呼ぶことを仮定し、すべてのインスタンス・スロットを適切に初期化し、適当なデフォルト値をセットし、型制約をチェックして、強制する。
なぜ、最近、なぜLarryがPerlがポストモダン言語と言ったはずと思ったのかを思い起こすと、言葉と物 C - たまねぎの状態 11に書いたからだ。もう忘れている^^;)
「プログラミングは難しい、スクリプティングをしよう...」(Larry Wall、Programming is Hard, Let's Go Scripting...、Oreilly perl.com THE SOURCE FOR PERL、2007-12-06)の「Text」の項を訳出しておこう。
最初が大文字の「テキスト」
私はポストモダンの観点から言語を読む。もちろん、ポストモダンの用語はそれ自身、文脈に敏感である。ある人々はポストモダニズムは民衆の権利拡大と大差ないと考える。ある人々はPerlについて同じことを意味すると考える。
しかし、私は、ポストモダニズムは、話されるか、書かれたいずれかのTextが両端の知性を、そして時にはその中間の知性を必要とするコミュニケーション活動であることを意味すると取る。私はおろかなコンピュータ言語に話しかけたくない。私は(私が)タイプした文字列を理解する(私の)コンピュータ言語が欲しい。
Perlはポストモダン言語である。そして、多くの保守的な人々はポストモダニズムはむしろ進歩的な概念のように感じる。だから、ポストモダニズムに関する私の物の見方が、宣教師、特にthe Wycliffe Bible Translatorsに教えられるように言語学や翻訳を勉強することによって知識を与えられたことは皮肉である。彼等が力説したことの一つは、実際、未開の人間言語のようなものはないということである。彼等が本質的に主張するところは、すべての人間言語は「チューリング完全」であるということである。
あなたが、いわゆる未開部族のところに行き、彼等の言語を分析すると、構造的にそれが他の人間言語と同程度に複雑であることを見出すことになる。基本的に、あなたが十分に長く使用すれば、人間言語でかなり多くの事柄を話すことができる。強いて言うなら、人間言語は「チューリング完全」である。
人間言語はそれゆえにあなたが言うことができることにあるのではなくむしろ、あなたが言わなければならないことにある。英語では、単数と複数を区別することを強いられる。日本語では、単数と複数を区別しなくてよいが、話しかける人への尊敬の度合いだけでなく、話す人や物についての尊敬の度合いを考慮して、特定のレベルの礼儀正しさを取らなければならない。
(以下は既に訳した。→ 言葉と物 C - たまねぎの状態 11)
放り投げたはずのポストモダンが思いがけず戻ってきてしまったので、今度は地球周回軌道まで打ち上げておいて、オブジェクトの話に戻ろう。ドッカーン・・・3万6千キロメートル上空へ。ポストモダンはしばらくは戻ってこないだろう。
最新のたまねぎトークの「immutable classes / mutable classes」の項を訳してみよう。
不変クラス / 可変クラス
Javaのクラスは閉じられている。その理由の一つはJavaがかなり速く走ることができることである。逆に、Rubyのクラスは開かれている。それが意味するところは、あなたはいつでも新しいものをそれに付け加えることができることである。開く選択を維持することの理由の一つはたぶんRubyがゆっくり走ることである。が、その柔軟性はRubyがRailsを持つ理由でもある。
Perl 6は不変総称(generics)と可変クラスの興味深い混合をここに持ち、時にクラスを閉じることを可能にすることについて興味深いポリシーを持つだろう。例えば、クラスはそれ自身を閉じたり、終了させることはけっして許されない。ごめん、ある理由で私はPerl 6について話し続けている。それはPerl 6をデザインするすべてのこれらの次元について考えなければならなかったという事実と関係がある。
この項は、Mooseが登場する「class-based / prototype-based」の項の前にある。
総称とは、データ型を無指定にしておけるクラスで、データ型は継承したくないようなクラスに用いるらしい。Perl 5ではデフォルトみたいなものだから、OOPの第12章総称、12.1のタイトルは「Perlに特別な総称メカニズムが不要な理由」となっている。型のあるPerl 6ではそういうことでもないのだろうけど、Synopsis 12: Objectsにはgenericsという項目は見当たらないが、・・・roleがその役割を担うのかな?・・・Open vs Closed Classesという項目はあるが・・・
物理学は数学言語を使って、素粒子から宇宙までのスケールの時空の構造を描き出す。例えば、言葉と物 LXXXVII - E8の記事にあるように。超ひも理論は10次元の理論であるが、次第に理論は複数あることがわかってきて、それを統合するのが、11次元のM理論である。Mは母(Mother)のMである。ローレンス・M・クラウス著『超ひも理論を疑う - 「見えない次元」はどこまで物理学か?』(早川書房、2008年)では、超ひも理論は次元の巻上げを疑われているようだが、Perl 6は宣言をまっすぐに保つことによって次元を巻き上げずにおけるらしい。プログラミング言語は何を描き出すのだろう。
テキスト処理の世界はインターネットがもたらされて以来、大きく変化した。それ以前のテキストは基本的にはプレーンテキストだった。初期のテキスト処理は特殊なマークアップによってワードプロセッシングを実現するような仕組みが中心だった。テキストをXTR+TBLやFINのようなツールで処理すると、Excelなどで作られたような複雑な表を含む整形された文書がページプリンタから出力された。そのこと自体が驚きだった。1980年代後半のことだったろう。1990年代に入って、テキスト処理の素材の中心となっていったのは、パソコン通信のログだった。1990年代、NifTermやAirCraftなどのNIFTY-SERVEのブラウザが全盛を迎えるとほぼ同時に、WWWが一般ユーザーに普及しはじめる。Windowsの時代になって、僕にとってはスクリプティング言語はデスクトップのツールとして行き場を失いつつあった。DOS窓ではエスケープシーケンスが機能しなくなったからだ。
CGIが登場したのはそれほど昔でもない。インターネットが普及したのと同時期、1995年ぐらいだったらしい。最初にCGIを知った時はそれほど興味は持てなかった。まだHTTPだの、LWPモジュールなど知らなかったせいもある。パソコン通信のログのほうが優勢な時代だったのである。HTMLでマークアップされたテキストが、Webに溢れるようになったのは、21世紀に入ってからだろう。LWP::Simpleモジュールのget関数で、任意のURLのHTMLテキストをスクリプトで読み込めると知った時は、インターネット時代のテキスト処理の大きな可能性を感じたものだ。それがデスクトップCGIとなって「実践実用Perl」を生み出した。スクリプティング言語の主戦場は、デスクトップにおいてもWebブラウザとなったのである。少なくとも僕にとっては・・・
テキスト処理は、行単位でテキストを読みながら、パターンマッチで必要な情報を抽出し、一塊のデータとしてまとめながら出力する技術である。他の情報を付加した合成出力も可能だし、プログラム自身を出力することさえ可能である。テキストからなるものを生み出すことにおいては、事実上不可能なことはない。おそらく、データの入力や実行制御の方法に関わるインターフェースとデータをどのように保持するかに関わるデータベース化が、フレームワークとしてシステム化するためには重要な部分だろう。
話は複雑な構造に行き着くはずだった。Perl 4では、一塊のデータを、単にタブで区切られた文字列の値と一意となる文字列をキーとする連想配列とし、DBMに格納するのが常套手段であった。それがMySQLのようなRDBが自由に使えるようになって、少し使い始めたが、データベースの生成のところが面倒くさい。それで、MLDBMにデータを複雑な構造のまま格納するという話を書く予定だった。しかし、複雑な構造とは何だろうというところで、気分は他のところに飛んでいってしまったのだ。
この複雑な構造とやらで何をするんだい、うーむ、必然性を感じられるネタがないかなとしつこく考えている^^;)
Perlではサブルーチンを呼び出すときに、&をサブルーチン名の先頭に付ける。それが、なぜか、&を付けなくても呼び出せるようになった。このようなしゃべり方もやはりPerl 4プログラマから抜けきっていなかった僕の状態を表す現象の一つである。もっとも気付いたのはだいぶ以前の話ではあるのだが。モジュールのメソッドを呼び出す場合(関数呼び出し)がその典型である。しかし、なぜ、そんなことができるのかは理解していなかったのである。これは旧式のサブルーチンの話ではなかったのだ。
サブルーチンはプロトタイプを利用すれば、サブルーチンを宣言する場合に、引数の個数や型に制約を加えることができる(プログラミングPerl改訂版、2.7 サブルーチン、2.7.3 プロトタイプ、133ページ;プログラミングPerl第3版 Vol.1、6章、6.4 プロトタイプ、261ページ)。Larryが「Mooseは本質的にPerl 6のオブジェクトモデルのプロトタイプである」としたのは、このプロトタイプのことを指しているらしい。プロトタイプのサブルーチンとして呼び出す場合には、&を付けずに呼ぶ(関数呼び出し)。&を付けると制約がなくなる。これは総称メカニズムと関係があるのかな・・・OOP(Object Oriented Perl; ダミアン・コンウェイ著「オブジェクト指向Perlマスターコース オブジェクト指向の概念とPerlによる実装方法」、ピアソン・エデュケーション、2001年)ではプロトタイプのメカニズムの話は出ていないようだ。ちなみにPerlにプロトタイプが実装されたのは、5.002からである(perlhist - the Perl history recordsには「Larry 5.002 1996-Feb-29 Prototypes.」とある)。
ここで、Programming is Hard, Let's Go Scripting...の「early binding / late binding」を少し訳してみよう。
早い束縛 / 遅い束縛
この文脈の束縛は、あなたが任意のルーチン名で呼び出そうとするルーチンを決定する時点に生ずるのが大体正確なところである。コンピューティングの初期においては、ほとんどの束縛は効率の理由からかなり初期になされた。コンパイル時か、遅くともリンク時である。静的に型付けされた言語にまだこのアプローチを見ることができる。しかしながら、我々はSmalltalkのような言語に異なった傾向を見始めた。そして、今日では、ほとんどのスクリプティング言語は遅い束縛に向かう傾向がある。それが、スクリプティング言語がdwimmy(どういう意味^^;)である(意味するところをする)ことを試みる理由であり、最も意味のあることをする(dwimmiestな)決定は、通常は遅い決定になる。なぜなら、より利用できる意味的、実用的文脈を持って作用するのは、その時だからである。さもなければ、あなたは未来を予言しなくてはならない。それは難しい。
それで、スクリプティング言語は自然にオブジェクト指向の視点へ動いていく傾向がある。そこでは、メソッドが仕事を片付ける時間まで束縛は生じない。C++やJavaのような言語に衝突の傷をまだ見ることができるが、C++はデフォルトのメソッド型を非仮想的に作るので、あなたは仮想的に明確に、遅い束縛を得ることを言わなくてはならない。Javaは最終クラスの概念を持ち、本質的にコンパイル時に呼び出しをクラスに結びつけることを強いる。私は、両方のこれらのアプローチは大きな過ちだと考える。Perl 6は異なる過ちを犯すだろう。Perl 6においては、すべてのメソッドはデフォルトで仮想的である。全体として、アプリケーションのみが、クラスを仕上げるようにオプティマイザに告げることができるが、おそらく、あなたが、いかにすべてのクラスが、プログラムにおいてすべての他のモジュールによって使われようとしているかを知った後である。
この部分にSmalltalkが出てくるが、「Prototype-based Object」で検索すると、Vladimír Janoušek氏の「On the Prototyped-Based Object Orientation in Systems Modeling and Simulation」が引っ掛かる。ここでは、C++やJavaで実装されたDEVSというシステムをSmalltalk(実際にはSqueak)で実装して、より柔軟なアプローチをサポートできることを示している。Smalltalkの拡張、package Prototypesを使う。これがSmalltalkについてLarryの言っていることだろう。
『ダミアン・コンウェイ著「オブジェクト指向Perlマスターコース オブジェクト指向の概念とPerlによる実装方法」(ピアソン・エデュケーション、2001年、以下OOP)ではプロトタイプのメカニズムの話は出ていないようだ。』では「総称」の章を探しただけだったので、インデックスで「プロトタイプ」を調べた。
オブジェクト指向のメソッドでは、サブルーチンのプロトタイプは無視されるというのが結論である(3.2 Perlの単純なクラス、「メソッドのプロトタイプ」、119ページ)。オブジェクト指向モジュールでは関数呼び出しをしないことで、プロトタイプは有効にならないことになる。なあるほど、そうなのか。「Perlコンパイラがプロトタイプをチェックできないのは、Perlのすべてのメソッドが多態的であるためだ。・・・」としていて、第6章「継承」にその説明がある(6.1.2 Perlでの継承の意味、234ページ)。
それはともかく、やはりDamian Conway著である「Perlベストプラクティス」(オライリー・ジャパン、2006年、以下PBP)では、副作用のあるサブルーチンのプロトタイプは使うなということになっている。「オブジェクト指向実装では、どのメソッド呼び出しであっても完全に無視されるために、無害であるかのような錯覚を抱かせる」とある(9章 サブルーチン、9.10 プロトタイプ、212ページ)。
結局、Perlのオブジェクトはどのように使うのか。OOP(2001)では、クラス生成の自動化(第8章)にClass::StructとClass::MethodMakerが紹介されているがまだ物足りない感じ、PBP(2006)では、Class::Stdが一貫して紹介されている。Class::Stdはinside-outオブジェクトを取り扱えるのだろう(オブジェクト指向プログラミング - 裏返しオブジェクト?!)。そして、Perl 6の影響を受けたポストモダンオブジェクトシステム、Moose/Class::MOPの登場となったということなのかな。
キーワードはメタクラスで、Class::MOPはSmalltalkやCLOS(Common Lisp Object System)の影響を受けている。ざっくりとしたPerlのオブジェクト指向の流れは掴めたので、そろそろMoose/Class::MOPへ戻ろう。
MooseやClass::MOPのドキュメントには様々な論文が参照文献として記載されている。そういう文献を調べてみると、主にSqueakなどのSmalltalk系言語が使われている。
オブジェクト指向プログラミングを勉強する場合に最初に閉口するのは、知らない用語が多すぎることである。しかし、これには慣れていく必要がある。クラスとは何か、オブジェクトとは何か、そしてメタクラスとは何か。その他にも、様々な用語が溢れ出し、溺れそうになる。そのような用語を自在に使えるようになる時は、オブジェクト指向を自家薬籠中のものとできたときだろう。Class::MOPのドキュメントが参照している「Uniform and safe metaclass composition」(Stéphane Ducasse, et al., "Computer Languages, Systems & Structures", 31, 2005, 143-164)の要約から少し引用訳出してみよう。
純粋なオブジェクト指向言語においては、クラスはオブジェクトであり、メタクラスと呼ばれる他のクラスのインスタンスである。クラスがそのインスタンスのプロパティを定義するのと同じ方法で、メタクラスはクラスのプロパティを定義する。それゆえに、クラスのプロパティを再使用しようとすることは非常に自然であり、いくつかのクラスの間でそれを利用することができる。しかしながら、これは、「メタクラス構成問題」を引き起こす。すなわち、あるクラスに適用されたコード断片が、それぞれのメタクラスの継承関係により、他のクラスに適用された時に壊れてしまう。
Moose/Class::MOPの作者のStevan Little氏は、その前にClass::Traitを書いた。Traitsという概念は重要だと思われる。Perl 6のSynopsis 12: Objectでは、traitという用語は普通名詞で使われる。traitは遺伝学では形質という意味だ。クラスのプロパティに近い意味で使われる。より基本的な単位、挙動の構成可能な意味的な単位となるべきものなのだろう。
Class::Traitの参照文献「Traits: The Formal Model」のやはり要約の最初の部分を引用訳出しよう。
Traitsは挙動の再利用単位であり、オブジェクト指向プログラムにメソッドのレベル以上ではあるが、クラスのレベル以下の構造化のレベルをもたらす。
そろそろ継承の問題に足を踏み込まなくてはならない。Class::MOPのMOPは「Meta Object Protocol」の略である。複数のオブジェクトには約束事を持ち込まねば、メタクラス構成問題が生じるのは当然のことである。いよいよオブジェクトも人間臭くなってきた。Stevan Little氏はMooseを最初、Complete Modern Object Systemと呼んでいたのだが、結局、Postmodernと呼ぶことにした。人間は完全ではありえないが、完全を求め続けるのである。未来に向けて。
何か日曜日にだけ書くみたいな日々が続いている。やれやれ。お疲れだが。うむ、オブジェクト指向の研究にPerlだけを見るのもなんだなと思い、「Python入門」(1998)、「Pythonプログラミング」(1998)、「初めてのPython」(2000)を見なおしてみる。しかし、これらの入門書ではそれほどオブジェクト指向を売り物にしていない。classは便利だから使いなという程度。確かにPythonがオブジェクト指向だという意識はそれほどない。やはりオブジェクト指向はRubyかなと、その名も「オブジェクト指向スクリプト言語 Ruby」(1999)を引っ張り出す。
オブジェクト指向について勉強するには大変詳しく実際的なので興味深い。プロトタイプベースのオブジェクト指向や「クラス合成」の問題についても言及がある。書かれたのが1999年なので、Traitsについてはない。ruby-talkを「traits」で検索した結果のトップ2件をピックアップ。調べてみると、traits-0.0.0が出たのが2005年である。Ruby-Traitsは2007年リリース。
WikipediaでTrait (abstract type)を見ると、RubyのModule mixinsはある程度traitsに似ているとあった。「オブジェクト指向スクリプト言語Ruby」のMix-in(177ページ)には、Mix-inクラスは、「インスタンスを持たない抽象クラス」であり、かつ「Mix-in以外のスーパークラスを持たない」とある。
まつもとさんの2004年の日記にTraitsへの言及があった。
オブジェクト指向は奥が深い。Prototype-based programmingを調べた。クラスのないオブジェクト指向プログラミングの一種ということらしいのだが、・・・。WikipediaのLanguagesの項のリストのPerlの部分を見ると、Class::Prototypedのモジュールへのリンクがある。このモジュールのsee alsoには、Class::Classlessへのリンクもある。
Synopsis 12: Objectsには『Perl 6においては、クラスオブジェクトを含め、すべてのオブジェクトはそのメタクラスのインスタンスに委譲する。HOWメソッドによってオブジェクトのメタクラスを得ることができる。「クラス」のオブジェクトは「空(から)」のインスタンスと考えられ、より適当には「プロトタイプ」オブジェクト、あるいは「プロトオブジェクト」と呼ばれる。』とある。Perl 6では、Traitsやメタクラス・プログラミングの概念がプロトタイプに結びついているように見える。これが、MooseがPerl 6のプロトタイプと言われる所以である。あまり用語に拘っているとわけがわからなくなるかもしれない。
Perl 6 Design Minutes for 05 March 2008の話によれば、Larryが、Perl 6の標準文法をPerl 5で動かそうとしている!? Perl 5の型システムの制約がオブジェクトを獲得するのを難しくしていて、Mooseを使うというアイデアについてのLarryのコメントもある。Larryはperl5 to perl6 translatorを書いているはずだが、逆の方向の話が出ているのはなぜだろう。Perl 6 Design Minutesの断片的な会話から意味を取るのは大変難しい。おそらく、そのようなtranslatorはa2pのようなわけにはいかない。Perl 5のなかで、Perl 6を表現できるようにすることがtranslatorには最低必要なのかもしれない。そして、その時には、C版のPerl 6ができるということであるかもしれない。
昨年末のLarryの「プログラミングは難しい、スクリプティングへいこう」の記事で、Mooseに出会って、オブジェクト指向を見直すきっかけとなった。プロトタイプベース・プログラミングは、クラスのないオブジェクト指向プログラミングというよりは、メタクラスのあるオブジェクト指向プログラミングとなりつつある。メタクラスはクラスのプロトタイプを生み出す。Perlのサブルーチンのプロトタイプ(関数指向)がオブジェクト指向によって一般化・拡張されたものであると見做せるのかもしれない。
Perl 6のHOWメソッドによって、Larryが予感しているように、メタクラスは考えうる限りだけ存在するだろう。世界を被い尽くすまで。Stevan Little氏がMooseを完全にモダンなオブジェクトシステムと最初は豪語していたのを後で謙虚にポストモダンと言い換えたように、世界の見方はいくつもある、超ひも理論がいくつもあるように。Moose/Class::MOPの発展が今後の大きな楽しみである。
さて、ここから、ミシェル・フーコーへと展開する道もあるが、それはまた別の楽しみとして取っておいて、Moose実践実用の思索に戻ろう。
オブジェクト指向モジュールをどのように書くのがよいか試したりしている。継承のサンプルを作りたいのだが、まだ適当な構成のイメージが浮かばない。
試したのは、出力するHTMLを一つのメソッドで出力できるようにするために、YAML形式の地域情報を読み込むための部分をCreateGMap.pmに取り込んで、gmapメソッド一つにまとめること。YAMLファイルのフルパスを変数として加える。このようにすると、ほとんど無意味で不自然なヘッダ出力、ボディ出力、フッタ出力のメソッド分割はなくなる。HTMLテンプレートとパラメータを載せた大きな一つのコンテナができあがる。本体のスクリプトからは、CreateGMapだけの使用を宣言し、コンストラクタを作ってメソッドを一つ呼ぶだけで済むようになる。
package CreateGMap; use Moose; use CreateGMap::Area; use YAML qw(LoadFile); has 'baseurl' => (is => 'rw', isa => 'Str', default => '');# マーカーデータ中の相対URL補完用 has 'key' => (is => 'rw', isa => 'Str', default => '');# Google Maps KeyのURL文字列 has 'title' => (is => 'rw', isa => 'Str', default => '');# ページタイトル has 'desc' => (is => 'rw', isa => 'Str', default => '');# ページの説明 has 'id' => (is => 'rw', isa => 'Str', default => 'map');# Google Mapの表示位置 has 'width' => (is => 'rw', isa => 'Int', default => 500);# Google Mapの幅 has 'height' => (is => 'rw', isa => 'Int', default => 600);# Google Mapの高さ has 'messageid' => (is => 'rw', isa => 'Str', default => 'message');# Google Mapのセンター経度緯度表示位置 has 'lng' => (is => 'rw', isa => 'Num', default => 132.472833);# 経度 has 'lat' => (is => 'rw', isa => 'Num', default => 34.385555);# 緯度 has 'data' => (is => 'rw', isa => 'Str', default => 'data.xml');# マーカーデータファイル has 'zoom' => (is => 'rw', isa => 'Int', default => 1);# Google Mapの縮尺設定 has 'areafile' => (is => 'rw', isa => 'Str', default => 'C:/full/path/area.txt');# YAML形式地域情報ファイル sub gmap { my $self = shift; my $html = <<HEADER; Content-type: text/html; charset=UTF-8 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"> <head> ..... </head> HEADER $html .= <<BODY; <body onload="onLoad($self->{lng}, $self->{lat}, '$self->{data}', $self->{zoom})"> <h3>$self->{title}</h3> <p>$self->{desc}</p> <hr> <table border=0> <tr> <td> <div id="$self->{id}" style="width: $self->{width}px; height: $self->{height}px"></div> <div id="$self->{messageid}"></div> </td> <td valign="top>" <table> BODY ### 地域情報のYAMLファイル読み込み my @hashref = LoadFile($self->{areafile}); foreach (@hashref){ my $area = CreateGMap::Area->new(%$_); $html .= $area->tableunit; } ### $html .= <<FOOTER; </table> </td> </tr> </table> ..... </body> </html> FOOTER return $html; } 1;
CreateGMap::Areaモジュールは前と同じものを使う(言葉と物 CIX - Mooseの研究 I まえがきなど)。本体のスクリプトは次の様に簡単になる。
#!/Perl5.8/bin/perl.exe use CreateGMap; my $gmap = CreateGMap->new( baseurl => '<- リンクURLが相対的な場合に他のサイトに表示する場合に使う ->', key => '<- Your Google Maps Key ->', title => '<- Page Title ->', desc => '<- Page description ->', areafile => 'C:/full/path/area.txt' ); print $gmap->gmap;
このサンプルはPerlスクリプトとしては少し単純すぎるが、複雑な要素の大部分は、モジュールに書き込まれたHTMLテンプレートの中に含まれている。HTMLのメタデータ要素、CSS、Google Maps用のJavaScriptコード、Ajaxによる表示用のためのHTML要素、tableタグによる地図と切替え用地域情報の配置、コピーライト、Google Analytics用のJavaScriptコードなど。テンプレート部分だけでも3種類の人工言語が自然言語中に埋め込まれており、変数はPerlで記述されている。テンプレートの構成要素をさらに細かく制御できるようにしようとすると、また別の言語を生み出しかねないのではあるが、他の人に使ってもらうためには、ワンパターンを受け入れるのであれば、もう少しパラメータをテンプレート用に付け加えておくぐらいでよいだろう。
このようにモジュール化を考えてみると、HTMLの構造が複雑化しているのがよくわかる。Google Map部分の表現はJavaScriptが大部分を占めているし、地図のマーカーデータは、XML形式で読み込まれる。HTML、JavaScript、XML、CSS、Perl、YAML、そして自然言語を含めて、なんと7種類の言語を使用する複雑なハイブリッド言語システムとなっているのだ。もっともYAMLは地図の地域の切り替えデータを導入するために、Perlは動的なHTMLの生成のために、僕が付け加えた言語である。YAMLはXMLかJSONでもよいだろうし、Perlの部分はJavaScriptに置き換えられるかもしれない。
なぜ言語システムは複雑化するのか。世界を表現するための多様な表現力を獲得するためである。Perl 4について書かれたPerlプログラミングの初版赤本(1993年)は633ページ、Perl 5について書かれた第2版の青本(1997年)は759ページだったが、Perl 5.6について書かれた第3版(2002年)は、2分冊になり計1303ページとなった。何が増えたのか、まったく新しいものはUnicodeぐらいだろうが、スレッド、セキュリティ、CPAN、プラグマモジュールなど、大きな項目になっているものも多い。関数や正規表現など言語仕様も拡大したのだろうが、時代とともにライブラリが増え、ドキュメンテーションが進んだことも大きな理由だろう。内容が豊富になれば、当然分量が増えるが、それは一貫して自然言語で記述される(一部はPerlコードであり、原書は英語であるわけだが・・・)。しかし、このお話しは人間の暗黙知の共有化における自然言語上のプロセスに過ぎず、コンピュータ上の言語システムの複雑化とは関係ない。CreateGMapシステムは、コンピュータ上に世界を精緻に表現するための遠い道程の道草なのか、一時的な気の迷いなのか、定かではない。
昔は^^;)、万物は原子からなると考えられたが、今でもものごとの基本的な要素をatomと表現することも多い。それはさらに下部の構造を持っており、多様な素粒子の存在が検出されるようになる。さらにクォークが現われる。現在では超ひも、そしてDブレーン(brane;膜)が想定されるようになってきている。今のところ、コンピュータの基本はビットである。機械の上にどのような時空が構成できるのか、オブジェクト指向を廻る旅はまだまだ続くだろう。
サブルーチンのパラメータという言い方は、関数指向的な表現だと思う。関数なら変数(パラメータ)の値を入力するとサブルーチンに記された計算式に基づいて計算結果を出力するというイメージとなる。クラス(Perlならパッケージ)は関数(サブルーチン)の集まりのようにも考えられる。どこで、クラスがオブジェクトを生み出すようになったのか。
本日のタイトルは「特性と状態と糊」、この三つの要素を足すとクラスが出来上がるという話。Class::Traitの引用文献の類似文献としてだったと思うが、「Classes = Traits + States + Glue - Beyond mixins and multiple inheritance」(Mathanael Schaerli et al,The Inheritance Workshop at ECOOP 2002)をCiteSeerで見つけた。クラスの特性の集合から必要な状態を得るための糊が、すなわちメソッドである。
そうすると、traitsとは何かということになるわけだが、propertyやattributeと同じように見える。traitsの意味はもう少し調べてみよう。Mooseはクラスの属性にメタクラスの属性(Class::MOP::Attribute)に加えて、Moose::Meta::Attributeの属性を指定できる。これまでのMooseを使ったパッケージサンプルでは、普通のクラス(パッケージ)のnewメソッドを定義する代わりに、hasメソッドでクラス属性を定義する。クラス属性のアクセス定義、型定義、デフォルト定義などが可能である。特に型定義の属性は、コンテキストによって型の変化するダイナミックな言語においては、型が変化しては困る場合には、プログラムの一貫性を保つために重要なのだろう。
最先端から少し過去に遡って古い書き方と比較してみよう。まずは、実践実用Perlのオブジェクト指向Perlモジュールミニ入門の原始的レベルまで戻る。おそらく、当時はperltootのサンプルを参考に書いたはずだ。
package CreateGMap; use CreateGMap::Area; use YAML qw(LoadFile); sub new { my $self = {}; $self->{BASEURL} = undef; $self->{KEY} = undef; $self->{TITLE} = undef; $self->{DESC} = undef; $self->{ID} = undef; $self->{WIDTH} = undef; $self->{HEIGHT} = undef; $self->{MESSAGEID} = undef; $self->{LNG} = undef; $self->{LAT} = undef; $self->{DATA} = undef; $self->{ZOOM} = undef; $self->{AREAFILE} = undef; bless($self); return $self; } sub baseurl { my $self = shift; if(@_){ $self->{BASEURL} = shift }; return $self->{BASEURL}; } ..... sub areafile { my $self = shift; if(@_){ $self->{AREAFILE} = shift }; return $self->{AREAFILE}; } sub gmap { my $self = shift; my $html = <<HEADER; Content-type: text/html; charset=UTF-8 ..... <head> ..... <title>$self->{TITLE}</title> ..... } 1;
起動するには、これまでのサンプルとは少し違う。
use strict; use warnings; use CreateGMap; use CreateGMap::Area; use YAML qw(LoadFile); my $gmap = CreateGMap->new(); $gmap->baseurl('<- リンクURLが相対的な場合に他のサイトに表示する場合に使う ->'); $gmap->key('<- Your Google Maps Key ->'); $gmap->title('<- Page Title ->'); $gmap->desc('<- Page description ->'); $gmap->id('map'); $gmap->width(500); $gmap->height(600); $gmap->messageid('message'); $gmap->lng(132.472833); $gmap->lat(34.385555); $gmap->data('data.xml'); $gmap->areafile('C:/full/path/area.txt'); $gmap->zoom(1); print $gmap->gmap;
この方法でも起動時にオーバーライドできるので、undefの代わりにデフォルト値を設定しておくこともできる。
プログラミングPerl第3版(オライリー・ジャパン、2002年)の373ページ(Vol.1)に紹介されている方法(12.4.2 イニシャライザ)を使ってみよう。
package CreateGMap; use CreateGMap::Area; use YAML qw(LoadFile); sub new { my $invocant = shift; my $class = ref($invocant) || $invocant; my $self = { baseurl => '<- リンクURLが相対的な場合に他のサイトに表示する場合に使う ->', key => '<- Your Google Maps Key ->', title => undef, desc => undef, id => 'map', width => 500, height => 600, messageid => 'message', lng => undef, lat => undef, data => 'data.xml', zoom => 1, areafile => 'C:/full/path/area.txt', @_, }; return bless $self, $class; } sub gmap { .....Mooseのサンプルのgmapメソッドと同じ } 1;
起動の仕方はMooseのサンプルと同じ。この方法でも通常の利用には機能的には十分だろうと思うが、なぜそのように書く必要があるのか、わかりにくい。Mooseは非常にスマートで、直感的にわかりやすいし、明示的である。
オブジェクト指向の目的がコードの再利用や大規模プログラミングの効率化であることは事実ではあるのだろうが、その程度のことなら、「言葉と物」シリーズで僕が取り上げるほどのことでもない話である。プログラミングは、特にテキスト処理は知識表現の一種であると考えてよい。コンピュータとネットワークは知識が蓄積され、かつ表現される場なのである。
知識の複雑な構造を表現する方法は進歩し、多様化してきている。昔ながらの書物はWikipediaのようにハイパーテキストで書かれたWebページに変貌するのだろうか。ワードプロセッサのファイル形式はXML形式で標準化されている。PDFのXML表現はどうなっているんだろう。テキスト、表、図、グラフ、画像、写真、ビデオ、そしてハイパーリンク、データベース。今やWebでは何でも取り扱える。Webにおける知識表現を考えることは言うまでもなく重要なことである。
さて、タイトルの答えは、永遠の課題でもあるだろう。さらなる探索と思索の旅を続けよう。
Wikipediaの知識表現のページは簡潔によくまとまっている。オブジェクト指向プログラミングで使われる用語は知識表現の用語と重なる部分も多い。「has」、「is-a」、「slot」などの用語は「知識フレーム」から来ている。オントロジーエディタのProtégéを見ていると、slotという入力項目があるのだが、その出所がわかった。
情報処理学会電子図書館で、会誌を「知識表現」で検索してみると55件がヒットする。オブジェクト指向に関わる記事として、溝口文雄氏の「オブジェクト指向概念による知識表現言語」(情報処理、Vol.29、No.4、Apr. 1988)という解説を見つけた。知識表現はマーヴィン・ミンスキーのフレーム理論(1975年)に基礎を置いている。
TSNETでBruce.さんから、言葉と物 CXIII - Mooseの研究 V プロトタイプの記事にコメント(2396. 更新日記にここでコメント [Bruce.] 2008/3/09(05:40))をいただいて、言い訳を少し考えていたら、Rakudoの意味を調べるはめに。意味をつきとめたので、言い訳と一緒に転載しておこう。
dwimmyのあとに「(どういう意味^^;)」と付けているのはふざけて書いているのですね。音的に似ているからです。最近は日本語がやたらに使われるようになっているから、引っ掛けて書いているのかなと一瞬感じたので。まあ違うでしょうけど^^;)、ふざけてみたのです。僕がやっていることは基本的には冗談半分なので、厳密性は問われると困りますけどね。事実には基づいているけど、ほとんど連想の記録ですから。書いてあることの妥当性はリンクを調べてご自分でご判断いただくということですね。僕自身は書きながらも内心疑問に思っていることは山ほどあるので、そのうち、調べていくはずで、次第に妥当なところに落ち着くでしょう^^;)
調べて書くのではなくて、書いて調べるという感じです^^;)書いているとどんどん疑問が湧いてくる。それを書いている時点に一応定着しているのが更新日記なので。
doyuimi→dwimmy
最近、Perl 6のことをRakudoって言うようになったのかな。よく調べてないけど。
Rakudo→駱駝?
調べました^^)
駱駝道を縮めて、楽土(パラダイス)に引っ掛けたのが真相のようで^^)
「駱駝道」を短縮して「Rakudo」にするという発想は表意文字のない英語圏ならではのものであるが、「楽土」に結びつけたので認可を与えよう^^;まあ、発音しにくいんだろうね^^)もっとも「楽土」も「極楽浄土」の短縮なんだろう。正式な語でもないような気がする。使うと「楽だどー」っていうわけで、Rubyに奪われたマインドシェアをホームマーケットで取り返したいとの願いが込められている。そうな^^;)