ToDo:
2学期最初の水泳。今日は、飛び込みを体験した。2つのグループにわかれて、プールサイドの飛び込み台からの飛び込み練習と、3,5,7,10mの飛び込み台からの飛び込みを交代で行うというものだ。
自分の居るグループは、前半に高飛び込みをするということで、まず、3mの所に行ってみるものの、いざ飛び込もうとすると、足がすくんでしまって、飛び込めない。しばらく他の人が飛び込むのを眺めていると、TAの人が、一度、10mがどんなものか見てみると良いというので、10mの飛び込み台に上ってみることにした。
10mの飛び込み台への階段を上がっていくと、上がっていくにつれて、どんどん怖くなっていく。マンションで、下が見える階段を上っているときは、あまり怖くないのに、何故、こういうときは怖くなるのだろうか。10mにたどりつくと、すさまじい恐怖を感じる。しかも、今日は風が強く、風に吹かれて落ちそうな錯覚すら覚える。これは絶対無理だと思いつつ、3mのところに戻ったが、結局、交代の時間まで、3mのところからすら飛び込むことができず、自分がチキンであることを、思い知った。
後半は、プールサイドの飛び込み台からの飛び込み。これはさすがにできたが、飛び込み台が予想以上にはねるため、かなり怖かった。しかし、一度飛び込んでみると、なかなか気持ちいい。
そうして、何度かプールサイドから飛び込んでいるうちに、授業は終了。怖かったが、終わってみると、かなり楽しかった気がする。しかし、今回の授業は、水泳というより、度胸試しがメインだった気がする。
普段、Javaでプログラミングをしていて、これは欲しいという機能の1つに、代数的データ型がある。これは、関数型言語で一般的な機能ではあるが、オブジェクト指向言語などでは、あまり見かけない。
オブジェクト指向言語で見かけない理由としては、おそらく、クラスと継承を用いてほぼ同じことができるからだと思われる。しかし、プログラムを書いていると、しばしばデータのみを持つ構造体に近いデータで、あるグループに所属しているようなデータを必要とすることがある。このようなものは、しばしば、オブジェクト指向的でないと批判されるが、実際のところ、ときにはこのようなオブジェクトが必要になることはあると思う。そして、このようなタイプのプログラムは、クラスと継承で書くと冗長になりやすい。
例えば、Java言語で、抽象構文木を表現すると、次のようなプログラムになるだろう。
interface AST {}
interface Statement extends AST {}
interface Expression {}
class IfStatement implements Statement {
private Expression cond;
private Statement thenClause, elseClause;
IfStatement(
Expression cond, Statement thenClause, Statement elseClause
){
this.cond = cond;
this.thenClause = thenClause;
this.elseClause = elseClause;
}
public Expression getCond(){ return cond; }
public Statement getThenClause(){ return thenClause; }
public Statement getElseClause(){ return elseClause; }
public void accept(Visitor visitor){ visitor.visit(this); }
}
...
同じようなコードは、Standard MLで書くと、次のように書ける。
datatype ast = STATEMENT of statement | EXPRESSION of expression | ...and statement = IF of (expression * statement * statement) | ... and expression = ADD of (expression * expression) | ...
メンバ名のある無しなどいくつかの差があるので、完全に同じというわけではないが、Java版は、実に冗長に感じられる。このあたりをもう少し簡潔に書けるような文法を導入できないだろうか。
例えば、Scalaという言語では、case classesという構文があり、このようなものを比較的簡潔に書くことができる。 Onionでも、Scalaと同じような構文を導入できないか考えているが、このような機能がどれほど有用なものなのかが、いまいちわからない。コンパイラを書いていると、このような機能が欲しくなるのは確かなのだが、オブジェクト指向言語で一般的なアプリケーションを書く際に、このような機能は有用であるだろうか。
やはり言語としてそれを直接サポートする仕組みがあって、はじめて名乗ることができるのではないでしょうか。
それには同意します。問題なのは、言語して直接サポートというのが何を意味するかです。組み込みの構文としてという意味なら、RubyもObjective-Cもそんなのは存在していないわけで、RubyもObjective-Cもメッセージ指向ではないという話になってしまいます。とすると、おそらく標準ライブラリでそれがサポートされているというのが条件になると思います。一応、念のため言っておくと、ここで組み込みの構文というのは、メッセージを実行時に指定するための専用の構文が存在しているという意味です。例えば、Rubyの__send__は、ただのメソッドであり、専用の構文があるわけではないという話です。
他の言語でも、マルチスレッドライブラリを使えばスレッドを扱うことはできます。ですがそれをもって「マルチスレッドをサポートした言語」と名乗るのはおかしいですよね。やはり言語の機能として直接にサポートしてないと、名乗るのはおかしいわけです。
これも同じ話ですね。どこまでサポートすれば、言語の機能としてサポートしたことになるのでしょうか。例えば、Rubyでは、Javaでは組み込みの構文として実現されているスレッドの同期(synchronized)なども含めて、メソッドとして実現されていますが、Rubyはマルチスレッドをサポートしていないのかと言ったら、違いますよね。
JavaのReflectionは言語仕様に盛り込まれていますので、言語としてReflectionをサポートしているのは確かです。しかしReflectionはReflectionであり、メッセージングを直接サポートしたというのはちょっと違うんじゃないでしょうか。「できる」ことと「うまくできる」こととは違います。
「できる」ことと、「うまくできる」ことが違うのは了解しています。また、素のReflection APIを使うという話をしているつもりはありません。仮にReflection APIをラップしたものを、Objectクラスのinvokeメソッド(名前はcallでも何でもいいですが)として追加したとするならば、それは、メッセージングをサポートしたことになるだろうかというのが知りたいのです。
Javaがメッセージングをサポートするには、やはりそのための新しいバイトコードを導入する必要があると思うからです。ただしObject#invoke()である必要はなく、構文はなんでもいいかなと思います。
何故、バイトコードでサポートすることにこだわるのかがわからないです。もちろん、バイトコードでサポートした方が高速に実行できる(可能性がある)といったことはあると思いますが、求められている機能を実現するだけなら、リフレクションAPIのラッパーとしてObjectクラスにinvokeメソッドを追加するなどで十分なように思います。機能的に、リフレクションAPIでは実現できなくて、バイトコードで直接サポートした場合にできることというのは、何なのでしょうか?
これを見ればわかりますが、クロージャの中にメソッド名を埋め込まなければなりません。もちろんクロージャをオブジェクトとして扱うことができますので、実行時にクロージャを切り替えることはできますが、メソッド名を埋め込まなければならないことにはかわりません。
クロージャだと、結局内部にメソッド名を埋め込まなければならないことは確かですが、通常のGUIアプリケーションを作る分には、それで十分だと思います(GUIフレームワークの話については、後述します)。
メッセージを実行時に指定できると、GUIフレームワークの作成はかなり楽になります。例えば画面定義をXMLの設定ファイルに記述しておき、それをアプリケーション起動時に読み込んで画面を作成することを考えてみます。この場合、ハンドラメソッド名も設定ファイルに記述することになります。するとメソッド名はコンパイル時はわからず、アプリケーション起動時になって初めてわかります。
しかしクロージャを使う方法では、コンパイル時にハンドラメソッド名が分かってなければならないため、このようなGUIフレームワークが実現できません。実現しようとすれば、遅いのを我慢してReflectionを使うか、または実行時に動的にクラスを作成してロードする必要があります。最近はやりのバイトコードマニピュレーションですね。Reflectionやクロージャよりもこっちのほうが実用性は高いでしょう。
クロージャを用いても、同じような仕組みは簡単にできるように思います。要は、文字列に対してクロージャを結びつければ良いのですから、 キーが文字列で、値がクロージャであるようなマップをフレームワークが用意して、設定ファイルにはキーとなる文字列を指定するようにすれば良いだけではないでしょうか。あるいは、クロージャが結びつけられているプロパティを文字列で指定するようにして、リフレクションを使って、そのプロパティを取得するようにしてもいいでしょう。リフレクションを使うと、通常のメソッド呼び出しよりも遅くなるのは確かですが、GUIのイベントハンドラが呼ばれる頻度を考えると、そこがボトルネックになることはあまり無いように思えます。
今はGUIフレームワークの例でしたが、同じことはWebアプリケーションフレームワークでもいえます。例えばStrutsではアクションごとに個別のActionクラスを作る必要がありますが、これもJavaではメソッド名を実行時に指定できないからで、もし指定できれば1つのActionクラスに複数のメソッドを定義して実行することができるでしょう。これについては8/9の日記もご覧ください。
Javaの機能的な制約からそうしたというのは、一方的な見方でしょう。フレームワークの設計者としては、リフレクションAPIを用いてそのようにすることは可能だからです(このとき、フレームワークの利用者は、リフレクションAPIを直接触る必要は無いはずです)。また、静的型言語で、メソッド名を実行時に指定するようなフレームワークにすることには、静的な型チェックができなくなるというデメリットもあるわけで、どちらがいいかは簡単には言えないと思います。
メッセージを実行時に「取り替える」というよりは、実行時に「指定できる」という意味です。メッセージをあれこれ取り替えるためではなく、実行されるまでメッセージ名がわからない(実行されて初めてわかる)場合があるので、メッセージを実行時に指定できたほうがいいよね、という話です。
メッセージを実行時に指定できた方が良い場合も確かにあると思いますが、そのような状況がどの程度一般的なのかを考えることが重要だと思います。
その昔、まだJDKが1.02だったころは、Javaのメソッド名を実行時に指定できる機能を加えて欲しいという要望や提案はよくあったようです。しかしJVMの互換性を維持するために提案は受け入れられず、かわりに1.1でDelegationモデルが採用されました。もう絶版になってると思いますが、アスキーから出ていたという本に詳しく書かれています(同名で別の書籍があるのでご注意を)。大学の図書館ならあるかも。
『アドバンスドJava』は読んでいないのですが(今度、図書館にあったら読んでみます)、JVMの互換性維持を主な理由として、Event Delegationモデルが採用されたという風に書いてあるんでしょうか。自分は、静的な型チェックが可能なようにするために、あのような仕組みが採用されたと思っていたのですが。
言語仕様で決まってますので、「ライブラリとして実現」というのはちょっと違うかと思います。この機能はどちらの言語でも、メソッド呼び出しの内部の仕組みをプログラマーから触れるようにしたものであり、言語としてのサポートがないと実現できない機能です。ラッパーとして実現できるものではありません。
ラッパーとしてというのは、JavaのリフレクションAPIに対して言ったもので、RubyやObjective-Cに対して言ったわけではありません。あと、ライブラリとして実現というのは、単に組み込みの専用構文として実現されているわけではないという程度の意味です。
お土産にコートダジュールで、半熟ちーずなどを購入して、出発。湯河原駅の送迎バスの時間には、遅れて、送迎バスは行った後だったが、路線バスに乗って、無事、開始までに会場にたどり着くことができた。
自己紹介セッション
参加者全員が、3分程度で自己紹介を行うというセッション。自己紹介ということで、特に興味を引くことは無かったが、双子で大学院まで同じという人がいたのは、面白かった。聞いたところによると、別にお互いで示し合わせたわけでは無く、自然にそうなったそうな。うーん、謎だ。
数学とプログラミング -- 中学生向け教材の開発
早稲田大学の長慎也さんによる発表。長さん作のTonyu Systemを使った中学生向けの数学の補助教材の開発に関するお話。ゲームを開発するということを通して、数学の知識を学ばせるというのは、興味深いテーマだが、なかなか難しいと思う。デモを見た限りでは、プログラミングがメインなのか数学がメインなのかで揺れている印象を受けた。個人的には、なかなか面白いと思うので、頑張って欲しいと思う。
大学のe-learning教育システムについて
フェリス女学院大学の上坂明未さんによる発表。デモセッションのスライドを作りながら聞いていたせいか、内容をよく把握できなかった。
デモセッション
その名の通り、何らかのデモを行うセッション。まずは、笹田耕一さんによるYARVのデモがあった。従来のRubyインタプリタの遅さと、YARVの速さなどについてデモを交えつつ説明されていた。
その次に、自分によるOnion言語のデモ。Onionの言語仕様について、簡単に説明した後、いくつかのプログラムをOnionの処理系でコンパイルして、実行してみせた。しかし、笹田さんにも指摘されたのだが、いかんせんデモが地味過ぎた。もうちょっとグラフィックスを使うプログラム、例えばSwingなどを使ったデモの方が良かったかもしれない。
次に、長慎也さんによる携帯電話で動作するBASIC環境のデモがあった。言語としてはただのBASICだが、入力補完機能などがあり、携帯電話で入力することをよく考えて作られているようだ。まだソフトウェアは公開されていないが、公開する予定はあるらしいので、期待して待っていよう。
最後に、鈴木さんによるインセンティブコンピューティングのデモ。インセンティブコンピューティングというのは、名前を聞いたことがあるだけで、実際にどのようなことをするのかは、全く知らなかったが、どうやら、ユーザが計算力を提供するかわりに、何らかのデジタルデータ(MP3の音楽ファイルなど)の見返りを受けるようなシステムのことらしい。
夜セッション
別名、宴会。酒を飲んだり、参加者が持ち寄った食べ物を食べつつ、いろんな議論をしましょうというセッション。言語の話をしたり、暗号関係の議論を横で聞いたりして、過ごした。このときに、Onionの処理系をダウンロードして、実行してみようとした方がいて、下記のミスがわかった。やはり、ちゃんといろんな環境でテストしないとダメだなあ。
配布していたアーカイブにミスがあり、コンパイル・実行とも、Java1.5以上でなければ実行できないようになっていた。
具体的には、バイトコード操作ライブラリを使用している箇所の一部で、 org.apache.…パッケージを使うべきところを、間違ってcom.sun.…以下のパッケージをimportして使ってしまっていた。おそらく、クラス名を補完するときに、間違ってcom.sun.…パッケージをimportしてしまったのだろう。このせいで、ダウンロードしてくれた方の中には実行できなかった人もいたかもしれない。申し訳ない。この件は、9/15に配布予定の次のαバージョンで修正することにしよう。
Onionで以下のようなプログラムを書いたら、コンパイルが通って、しかも実行できてしまった。これは本来ならコンパイルエラーになるべきなので、バグなのだが、面白いのは、ちゃんと実行できていることだ。実行結果と逆アセンブル結果から考えると、どうやら、Java VMレベルでは、返り値の違うメソッドをオーバーロードしたものとして扱われたようだ。確かに、Java VMがオーバーロードを実現している仕組みを考えれば、できても不思議ではないのだが、驚いてしまった。
class A {
public:
method :Object { return "A"; }
}
class B extends A {
public:
method :String { return "B"; }
}
object :A;
object = new A;
System::out.println(object.method);//Aが表示される
object = new B;
System::out.println(object.method);//Aが表示される
System::out.println(object$B.method);//Bが表示される
起きて朝食を取った後、最初のセッションへ。
池崎正和さんによる発表。朝食を食べ過ぎて、うつらうつらしながらであったので、何を話していたのかがほとんど聞き取れなかった。
石井洋司さんによる発表。引き続きものすごく眠かったので、ほとんど聞き取れなかった。
暗号アルゴリズムMISTYなどの開発者松井充さんによる講演。松井さんの経歴、差分解読法や線形解読法の概要、MISTYの説明、最近の暗号関係のトレンドなど多岐にわたる内容だった。しかし内容が、少なくとも自分にとっては高度で、特に後半は内容の大半を理解することができなかったのが残念だ。これを機会に、暗号についてちゃんと勉強をしてみようか。
松田耕史さんによる発表。Ruby on Railsの紹介と、簡単なブログツール作成のデモ。なかなか興味深かった。ちょっとRuby on Railsを使ってみたくなったかも。
夕食後、近所の公園へ花火へ行って花火をした。どうやら、情報科学若手の会の毎年の恒例らしい。花火なんてするのは、何年ぶりだろう。すぐ終わってしまい、あまり情緒は無かったが、少し懐かしい気分になった。
当日参加者の中から発表者を募って、何かについて発表してもらうという企画。自分は、明日授業があるため、今日中に帰らなければならなかったので、最初の発表を聞いた後、帰ることに。明日授業があるのが、少し恨めしい。まあ、3年までに単位を取っておかなかったせいなので、自業自得ではあるけれど。
Onion関連でgoogleで検索していて見つけたページに、
×Lanugage
○Language
という記述があった。確かに、SourceForge.jpに登録したプロジェクト名を見ると、
Programming Lanugage Onion
となっており、確かにスペルを間違えたようだ。恥ずかしい。できれば、プロジェクト名を修正したいものだが、管理ページから直接変更することはできないようだ。メールで依頼するしかないのかな。
Looking Glassを自宅のPCで動作させてみた。自宅には、Linux環境が無いため、Windows上に、アメリカでがんばりましょう: Looking Glass Desktop を Windows で動かすのページをお手本にしてインストールした。以下は、スクリーンショット。操作方法は、まだよくわかっていないが、とりあえず、3Dのオブジェクトがデスクトップ上をふよふよと動いているのは、見ていて面白い。

今日は、午後7時頃走ったのだが、最近はこの時刻になると、もう真っ暗だ。筑波大を囲んでいるループ道路には、街灯がほとんど無い所も多い上に、歩道が結構でこぼこしているので、走っている途中で何度かつまずきそうになったりして、結構危ない。もう少し、街灯を増やしてくれたら有難いのになあ。
スクリプトを直接解釈して実行するモードが、ようやく動作するようになった。以下は、OOWebをOnionで動作させているスクリーンショット。
あと、今日こそはOnion0.1の次のαバージョンを出そうと思っていたのだが、実装予定だったスクリプトモードの実装はできたが、ドキュメントなどが全然揃っていない上に、Wiki上のドキュメントは、既に現状のOnionと乖離してきているので、週末にドキュメントを書いてから出すことにしよう。しかし、なかなか自分で決めた期限を守れないのは、ダメダメだなあ。あるいは、そもそも先に期限だけを決めてしまうのがダメなのかもしれない。
ちなみに、スクリーンショットで動作しているOOWebを動かすためのスクリプトは、以下。
import {
net.sf.ooweb.*;
}
def index :String { return "Hello, World"; }
def hello :String {
return
"<html><head><title>Hello</title></head>" +
"<body><h1>見出し1</h1></body></html>";
}
server = new Server("Example");
server.register("/", self);
server.listen;
_ ヨシタケ [今度はゆっくり走るよ。今回はがんばりすぎて、足がつかれちった。 ]
_ みずしま [了解。でも、つくばマラソンの時期には、あのくらいの速度で継続的に走れるようになりたいね。>今後はゆっくり走るよ。 ]
_ Robt Dimond [ * * * * * * * * * * * * * * * * * * * ..]
_ bellezza orale [ papa vibratore hombres eroticos amateur miss culetti d ..]
_ black gay men sex chat [ how to practice piano effectively hotel presidente cancu..]
以前から知ってはいたものの、試したことが無かったFindbugsを、Onionのソースのチェックに使用してみることにした。
FindBusというのは、コードをチェックして、潜在的なバグやバグを引き起こしやすいコードのパターンを検出してくれるツールであるが、同種のツールであるJLintやPMDがJavaソースコードをチェック対象としているのに対して、Javaバイトコードがチェック対象である点が異なる。また、ユーザがバグパターンを追加するといったこともできるようになっている。
使用するには、通常は、CUIまたはGUIのインタフェースのどちらかを選ぶことになるのだが、FindBugsには、Eclipse Pluginがあるので、それを使用してみることにした。使用方法は実に簡単で、パッケージエクスプローラでプロジェクトを右クリックして、メニューからFindBugs -> FindBugsを選ぶだけ。
さて、使用してみた結果は、検出されたパターンの全てが問題となるわけではなかったものの、いくつか本当のバグを発見してくれたケースがあり、助かった。例えば、if文とinstanceofを用いた分岐で、間違って、以下のようなコードになっていたが、このようなパターンをFindBugsは検出してくれた。使用方法も簡単だし、今後、継続してFindBugsを使ってみることにしよう。
...
else if(obj instanceof A){
// キャストできないはずの型にキャストしようとしている
doSomething((B)obj);
}
...
追記:
JLintは、Javaバイトコードも解析対象としているようなので、訂正しておく。
現在、Onionにはリストを表現するリテラルはあるものの、マップ(RubyやPerlで言うハッシュ)を表現するリテラルが無い。一応、スクリプト言語を名乗るからにはマップリテラルくらい無いと、とは思うのだが、どのような形式がいいだろうか。まず、真っ先に思いつくのは、RubyやPerlなどに見られる
{"hoge" => "foo", "piyo" => "bar"}
という形式だが、=>はタイプ数とシフトキーを押す回数が多いので(JIS配列の場合)、個人的にはイマイチだ。次に考えられるのは、PythonやJavaScriptなどの
{"hoge" : "foo", "piyo" : "bar"}
という形式だ。これなら、タイプ数も少なくて済むし、シフトキーも押さなくて良い。ただ、この形式は、Onionが型宣言に:を使っているのと、ブロック文に{}を使っているので、将来的にOnionで文末尾の;を省略できるようにしたときに、ブロック文の中に変数宣言を書いたのと区別が付かなくなりそうなのが微妙だ。例えば、
{
foo : bar
}
というプログラムがあり、文末尾の;は省略可能だとすると、構文解析時にはブロック文+変数宣言とマップの区別が付かない。いっそのことGroovyのように
["hoge" : "foo", "piyo" : "bar"]
という形式にするのが良いかもしれない。これなら、他の構文と衝突しないで済みそうだし、表現も簡潔だ。このような形式だと、空マップを表現するリテラルと空リストを表現するリストが衝突しそうだが、これについては、Groovyと同じく[:]で空マップを表現することで解決できるだろう。
ただ、この形式にも問題がある。現在、Onionの構文解析にはJavaCCを使っているのだが、JavaCCは基本的にはLL(k)パーザジェネレータなので、最初のkトークンを読んだ時点で、マップかリストかの判別ができない可能性があるのだ。一応、JavaCCはLOOKAHEAD(expression())のような形の先読みをサポートしているので、それを使えばいいのだが、構文解析が遅くなりそうで、微妙だ。
あるいは、リストリテラルと衝突しないようなプレフィックス(例えば#)をつけて、
#["hoge" : "foo", "piyo" : "bar"]
のようにするのもありか。最初に1つ余計な文字をタイプしなければならないのが痛いが、妥協できる範囲な気もする。
_ yach [英語キーボードだと確か:は[Shift]+[;]です・・・ ]
_ みずしま [タイプ数については、基本的にJIS配列での話だったんだけど(自分が使っているキーボードがJIS配列のものなので)。>..]
_ みずしま [ あ、もちろん、JIS配列の場合、{}については、シフトキーが必要だけど、それは考慮に入れていない。通常のプログラム..]
_ foto sesso orale [ lesbe golosas colonne doccia bukkake lesbe succhia pomp..]
_ inculata sborrata bocchino orgia [ piano man billy joel piano man cancun paradisio hotel ..]
_ sconfinato cowgirl prostituta [ fetish maduras peludas favoloso amatoriali dildo hardco..]
_ fiesta americana condessa cancun hotel [ hotel cancun foto bocca sborrata uk dental insurance p..]