K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[346] Re:プログラミング言語を作る
投稿者:mizu
2007/02/20 02:13:25

今回の投稿は、説明の都合上、大分長くなってしまいました。迷惑でしたら、 すいません。 >やってみるとそんなに難しくはないんですよね。実際、今回の企画はそれを >示そうと思ってはじめました。時間がなくてなかなか思うに任せていませんが。 ># そんなに難しくはない、ということを示したいんだから、あっという間に ># 実装できた方が説得力あるんでしょうけどねえ。 簡単に実装するなら、Lisp系言語などが楽でいいのではと思いましたが、 どうでしょうか。普通の言語に比べて、構文がちょっと特殊ですが、機能 拡張がわりと容易ですし、言語設計の面白さは十分に味わうことができるの ではないかと思います。 >・委譲の言語仕様とか、 基本的なアイデアとしては、いわゆる「単純委譲」をコンパイラが自動生成する というもので、Java風に書くと、 class MyList{ forward List list_ = new ArrayList();//委譲宣言 } というコードから、 class MyList{ List list_ = new ArrayList(); public void add(Object o){ list_.add(o); public Object get(index i){ return list_.get(i); } } というコードをコンパイラが生成します。もちろん、これだけだと メソッド名が衝突したときに問題が発生しますが、経験から言って、 そのような衝突は、おそらくさほど頻度は高くないだろうと思われるので、 コンパイルエラーにして、衝突したメソッドのみ、プログラマにどのフィールドに 委譲するか(あるいはそもそも委譲せず、そのメソッドを新たに定義するか)を 選択させれば良いと考えています。 あと、全部のメソッドを委譲するだけでは不便なので、委譲したくないメソッドを 列挙する機能も必要かなと考えていますが、これはまだ実装するかどうかわかり ません。 >・クロージャの実装方法(環境へのアクセス方法)とか、 実は、クロージャの部分はまだ実装できていないのですが、仕様は大体決まって いて、クロージャは、新たなデータ型を導入するのではなく、インタフェース の実装クラスのインスタンスとして、クロージャを生成するという方法を 取ろうと思っています。 ActionListener n = #(ActionEvent event){ System.out.println("actionPerformed"); }; というコード(#以降がクロージャの定義で、eventはクロージャの仮引数です)は、 class ActionListener$1 implements ActionListener { public void actionPerformed(ActionEvent event){ System.out.println("actionPerformed"); } } ... ActionListener n = new ActionListener$1(); というコードにコンパイルされます。 ここでは、ActionListenerがメソッドを1つしか持っていないため、クロージャ の定義では、メソッド名を指定する必要はありませんが、メソッドを複数持った インタフェースの場合、対応するメソッドを指定する構文を用意しようかと 思っています。 で、問題になっている環境へのアクセス方法ですが、クロージャから外側の 環境にアクセスしていることをコンパイラが検出したら、外側の環境での変数 へのアクセスをObject型配列の要素に対するアクセスに変換して、Object型配列 への参照を、クロージャに渡すという方法を取ります。例えば、 class Hoge{ public static void main(String[] args){ int n = 0; ActionListener listener = #(ActionEvent event){ n++; }; listener.actionPerformed(null); System.out.println("n: " + n); } } というコードは、 class ActionListener$1 implements ActionListener { private Object[] environment_; ActionListener(Object[] environment){ environment_ = environment; } public void actionPerformed(ActionEvent event){ environment_[0] = new Integer(((Integer)environment_[0]).intValue() + 1); } } class Hoge{ public static void main(String[] args){ Object[] environment = new Object[1]; ActionListener listener = new ActionListener$1(environment); listener.actionPerformed(null); System.out.println("n: " + ((Integer)environment[0]).intValue()); } } というコードにコンパイルされます。このようなクロージャの実装方式は、 クロージャを新たなデータ型として導入するのに比べて、正直使い勝手は 悪いですが、既存のライブラリを活用するという点では、この方式の方が 良いのではないかと思っています。 >・型宣言を省略する方法とか(静的型とのことなので、レキシカルな最初の代入から推測?) その通りです。例えば、以下の代入があったとして、 n = 1; 代入があった時点でのスコープで、nが宣言されてされていなければ、それは int n = 1; という宣言とみなされます。代入される値の型が参照型の場合も、同じですが、 nullが代入される場合だけやや特殊で、 n = null; は、 Object n = null; とみなされます。この機能があれば、例えば、よくある String line; while((line = reader.readLine()) != null){ .. } というコードが、変数宣言無しで、 while((line = reader.readLine()) != null){ .. } だけで書けるようになります(lineのスコープはwhile文で閉じています)。 以上、長々と説明を書かせていただきましたが、よろしければツッコミや 意見をいただければ幸いです。 > 公開される日を楽しみにしています。 どうも有難うございます。頑張って開発を進めたいと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]