投稿

ラベル(closure)が付いた投稿を表示しています

java7のロードマップ

すでにあちこちで反応があるようですが、アップデートされたjava7の ロードマップの件で、クロージャが含まれないようですね。    JavaLobbyの記事    InfoQの記事 私はblogでクロージャのこと書いていたので余計切ないなあ。 でも前から賛否分かれているので、まあ仕方ないのかなあと。 それより気になったのが  ・Reified generics なにこれ? "Reified"ってO'reilly「Java Generics and Collections」で盛んに出てきた 単語だけど... ちょっと調べた限りだと、型情報をRetentionPolicy.RUNTIMEでも保持し続ける ような仕組みらしいよ? こっちの方がずっと重要じゃないか。 これがJava7に含まれないほうがよっぽど悲しい気がしてきた...    

Javaのクロージャをいじってみた。(8)

何か、closureの引数でワイルドカード使うとエラーになる。 詳しく調べてないけど、以下のコードはエラーになった。 (BGGA 2008-08-11版のclosure.jarでやってエラーになった)  // × コンパイルエラー  // "? supre T"の周辺で6つぐらいエラーが出る。  public Integer calc({? super T,Integer} func) {   // ありゃエラーになる。  }  // ○ コンパイル/実行可能  public Integer calc(Function<? super T,Integer> func) {   // これはOK  } んー これは何か理由あっての制限なのかな。 それともこのバージョンは未完のためエラーになってしまうのかな。 英語だからってBGGAのページのドキュメントを読むのサボったから 見落としたのかな...。汗    

Javaのクロージャをいじってみた。(7)

unrestructured closureなるものが出てきた。キーワード==>とか。 このunrestructured closureの書きっぷり、Rubyのブロックっぽいな。 unrestructured closureを見てまずひらめくのは、多次元配列や コレクションのforeachメソッドかな。多次元でもひとつのforeach()で すべての要素をイテレーションする。 ↓こんな感じの。 //定義側 package xxxx; public class Matrix3 {   public int[][] elements;   public static void foreach(Matrix3 mat,                {int==>int} closure) {     int[] row = null;     int element = 0;     for (int i=0; i<elements.length; i++) {       for (int j=0; j<elements[i].length; j++) {         elements[i][j] = closure.invoke(elements[i][j]);       }     }   }   public Matrix3() {     elements = new int[3][3];     for (int i=0; i<elements.length; i++) {       for (int j=0; j<elements[i].length; j++) {         elements[i][j] = 0;       }     }   } } //利用側 import xxxx.Matrix3; import static xxxx.Matrix3.foreach;   ; void func() {   Matrix3 mat = new Matrix3();   foreach(int element : mat) {     element = 10;   } } というような感じ。 呼び出し側の記述は、":"の右側がforeach()の引数、左側は クロージャ==...

Javaのクロージャをいじってみた(6)

(※updated 2008-08-11のBGGAクロージャライブラリ使用) 1.return の記述 いまさら気づいたんだけど、returnのないクロージャの場合、 最後のステートメントは ; つける必要があるみたいね。 逆にこれがついていない場合はreturnがあるものとみなされるみたい。 // ○ 成功する {String str => System.out.println("Hello " + str); } // × コンパイルでエラーになる // [cannot use a void expression as a closure result]というエラー {String str => System.out.println("Hello " + str) } 2.戻り値無しのクロージャ型記述 あとクロージャの型はvoid型戻り値の場合、明示的にvoidを記述する必要が あるっぽい。引数は空でいいのに。 ...昔のblog記事見直すと{String=>}とか書いているので、 BGGAクロージャライブラリのバージョンによって違うのかも。 // ○ 成功する {String=>void} print; // × コンパイルでエラーになる // [required a type; found a lambda]というエラー {String=>} print; // これはOK {=>String} print; 戻り値として渡したいステートメントは、最後尾で ; が ついていないことが目印なのかも。(想像) {=>} とかいう型の書き方はなくなっちゃうのね。void型ぐらい無記名でも いいと思うんだけどなあ。 {=>void} ってリフレクションやJNIで利用する シグネチャの書式 ()V っぽいな。      

Javaのクロージャをいじってみた(5)

(※updated 2008-08-11のBGGAクロージャライブラリ使用) 6.static初期化ブロックに見えてこまる クラスのメンバにパッケージスコープのクラス変数として クロージャを宣言すると、static初期化ブロックと一瞬見間違える。 慣れの問題か? class Test { //たとえばこんな記述。static初期化ブロックに見えなくね? static { int, int => int } plus() { return {int x, int y => x+y}; } } 個人的なクロージャの記述スタイルの好みとしては、クロージャ型宣言の 記述スタイルは下のようなスペースを入れない方が好きだなあ。   {int,int=>int} // { int, int => int }   でもクロージャ本体の{}はスペース入れる派かも。 こちらの{}は普通のブロックと同じ意味と考えてるので。   // こんな感じ。 int sum = {int x, int y => x + y }.invoke(3, 4);   ちなみに私のC言語のポインタ記述は以下のとおり。   char* text; // char *text;   このポインタの例で私がクロージャ型宣言の記述スタイルについて 言わんとしていること、わかっていただけるでしょうか。 一種の"型"という意味の強調と、ブロックとしての{}と混同しない様にする ことが目的です。

Javaのクロージャいじってみた(4)

6.関数参照(Function Reference)   新しい記述が導入されるみたい。   クラス/インスタンスメンバへの参照は、"."演算子だが、   関数参照として新しく"#"演算子(みたいの)が導入されている。   このときは引数は型のみ記述している。メソッドを呼び出すというより、   クロージャとして取得したいメソッドのシグネチャを指定している感じ。   .netのデリゲート生成と似ている気がする。   例)   関数参照のコード String str = "Hello World !!"; {int,int=>String} subString = str#substring(int,int); // 引数も"型"を指定する --> ~~~~~~ System.out.println("subString=" + subString.invoke(0, 5)); // 出力:subString=Hello   逆コンパイルしたコード    finalも@Sharedも無しでコンパイルできたのは自動でfinal代入コードが   挿入されるためと判明。 String s = "Hello World !!"; final String binding = s; // このコードが自動挿入され変数がクロージャに渡される OII oii = new OII() { public final String _2B_invoke(int i, int j) { return binding.substring(i, j); } public final String invoke(int i, int j) { return _2B_invoke(i, j); } public volatile Object invoke(int i, int j) throws Throwable { return invoke(i, j); } final String val$binding; {...

Javaのクロージャいじってみた(3)

5.カリー化   メソッド内無名クラス定義ではfinal修飾子をつけたローカル変数を   無名クラス内部で利用することができるが、これを利用して   カリー化を実現している...みたい。   マイコミジャーナルの記事 にクロージャ内で利用したいローカル   変数には@Sharedアノテーションをつけることで利用可能になる   という記述があった。   へー   てっきり無名クラスのシンタックスシュガーだからfinalにしないと   駄目かと思っていたけど、ちょっと違うのね。   ……?あれ?私の試しているクロージャ実装(*1)ではfinalにも@Shared   つけなくてもコンパイル通るぞ??このバージョンの実装では文句は   言わないのかな?それとも@Sharedはクロージャのための機能じゃない   からjava7入れないとだめとか?   (*1 JDK1.6.0_10_bate, BGGAプロトタイプ実装2008-07-07版)   例)   javaクロージャでカリー化 //int local = 2; final int local = 2; {int=>int} func = { => {int num => num / local } }.invoke(); func.invoke(10); // 結果=5   上記コードの逆コンパイルコード final byte local = 2; II ii = (II)(new O() { public final II _2B_invoke() { return new II() { public final int _2B_invoke(int i) { return i / local; } public final int invoke(int i) { return _2B_invoke(i); } ...

Javaのクロージャいじってみた。(2)

4.自動でインタフェース継承  ・型推論   クロージャで記述すると自動的にインタフェースを継承してくれる。   いわゆる型推論ていうの?   いじってみた限りでは、以下の2つの記述で自動的に継承してくれる   ことは確認した。他のケースはしらん。     (1) 引数埋め込みで記述。     (2) クロージャの戻り値の型を継承したいインタフェース型で記述。   ・継承した場合メソッドはクロージャ型のinvoke()ではなく、    各インタフェースのメソッドとして扱われる。(内部処理的にはinvoke()    ぽいメソッドが生成されている模様。)   ・継承(実装)できるのはインタフェースだけで、抽象クラス/クラスは    継承できなかった。(コンパイルエラーになる)   ソースコード Functor<Integer> func = {Integer i => (int)(i * 2.4 + 68)};   逆コンパイルコード   // 呼び出し側   obj._fld1 = _2B_INSTANCE0; // 定義側 // 定数メンバとして定義される public static final _cls2 _2B_INSTANCE0 = new Functor() { // 戻り値型に継承されてる --> ~~~~~~~~~ public final int _2B_invoke(Integer integer) { return (int)((double)integer.intValue() * 2.39...9D + 68D); }     // ジェネリクスの場合、ブリッジメソッドもちゃんと生成されてる。 public final Integer calc(Integer integer) { return Integer.valueOf(_2B_invoke(integer)); } public volatile Object calc(Object obj) { return calc((Integer)obj); ...

クロージャ、java7での導入厳しいのかしら?

クロージャはjava7での導入の見込み薄い という書き込みを見かけた。 ソースを手繰るとjava7のメーリングリストっぽい。 ガーン。 BGGAのクロージャ実装、色々調べたのにー。 言語仕様の変化が大きすぎるのかー!? ……ん、ただのシンタックスシュガーだし関係ないか…。 (ここのClosure日記は、jdk1.6.0_10-bataでコンパイル/実行してる) だから逆に「そんなシンタックスシュガーごときいらん」 ということなのかな。ラムダ式楽しいぜ? Effective Java Second Edition に"Item21: Use function objects to represent strategies"という項目が増えてたりして、 Third EditionでのClosure項目追加の布石かしら? とか期待していたんだけどなあ。 でも一方でどこか安心している自分もいたり…。言語仕様の拡張を 好まないところはjavaらしいかなと。私がjavaを好む理由のひとつは 言語仕様拡張よりライブラリ提供での機能拡張を好むところだし。 まだ決まったわけじゃないし、来年のJavaOneの内容を楽しみに 待ちますかー。    

Javaのクロージャをいじってみた。(1)

イメージ
BGGAのクロージャサイト(http://javac.info/) の プロトタイプ実装をいじってみた。 マイコミジャーナルに概要を書いた記事があるようです。 今回いじってみたのは2008-07-07版と2008-07-13版のプロトタイプ実装。 JSRもドキュメントもちゃんと読まずにいじっているけど まあいいや。 1.単純実装の逆コンパイルして中身見る ・クロージャを用いたjavaコード public class SimpleClosure {   public static void main(String[] args) {     int sum = { int x, int y => x + y }.invoke(3, 4); // return 7     System.out.println(sum);   } } ・下のコードは上記コードをコンパイルし、jadで逆コンパイルしたコード import java.io.PrintStream; import javax.lang.function.III; public class SimpleClosure {   public SimpleClosure() {}   public static void main(String args[]) {     static class _cls1 implements III {       public final int _2B_invoke(int j, int k) {         return j + k;       }              public final int invoke(int j, int k) {         return _2B_invoke(j, k);       }     }     int i = _2B_INSTANCE0.invoke(3, 4);     System.out.println(i);   }   // ↓クロージャの実体(staticのメンバとして記述される)   public static final _cls1 _2B_INSTANCE0 = new _cls1(); } 逆コンパイルで気づいた点  ・クロージャの場合実際はstaticメンバとして宣言されるため...