Java 7で導入されるクロージャ

次期Javaでは,クロージャが導入されることになっている.クロージャとは,変数と束縛された関数のこと.Lispなどの動的な言語では数十年まえから一般的な機能で,昨今のスクリプト言語では無い方が珍しいぐらいなので,今更という感はなくもないが,導入されるのは大歓迎だ.

クロージャはさまざまな場面で使用できるが,最も多用されそうなのは,GUIなどのコールバックハンドラ.現在のJavaではクロージャが無いので,無名クラスを使って定義しているが,これをクロージャが置き換えるものと思われる.また,高階関数のようなものをつかうのにも便利に使えるだろう.

mycomジャーナルの記事1,2,3,4,5に良くまとまっている.

まだ,規格として安定したものになっているわけではないらしい.

Neal Gafterのブログクロージャの歴史が語られている.参考になる.

サンプル

上述のMycomジャーナルの記事から.

class AccessLocalVariable {
    public static void main(String[] args) {
        @Shared int x = 0;

        { int => int } add = { int y => x += y };

        System.out.println(add.invoke(5));
        System.out.println(add.invoke(5));
        ++x;
        System.out.println(add.invoke(5));
  }
}

見慣れない

{ int => int } add = { int y => x += y };

が,クロージャを参照する変数 add の宣言と,クロージャ本体の宣言.このクロージャは,引数を受け取ると,それをクロージャの外にある変数xに加算する.xには@Shared というアノテーションがついているが,これがないとコンパイラがエラーをだすらしい.

所感

なんというか,シンタックスはもうすこしなんとかならないのだろうか? intを引数にとるvoid型関数の型の書き方が

{ int => void }

だというのは,これだけをとればおかしくはないが,Javaのメソッドでは,

void func(int a) ..

というように,返り値の型,引数の型の順番で書くということを考えると,やはり違和感がある.

また,既存のGUIのハンドラは,いくつものメソッドを持つListener型のオブジェクトを引数にとるように設計されているので,このListenerをクロージャでリプレイスするのはそう簡単ではないだろう.

提案者の一人Neal Gafterの講演のスライドを見たら,制御構造にも利用できるような,クロージャを定義しようとしているようだ.これはこれですばらしいような気もしてきた.しかし,すでにJavaは破綻寸前だ.Genericsまわりも破綻しているっぽいし,配列とCollectionsの不整合も,いやになる.もう一度別の言語をゼロから設計した方がいいんじゃないだろうか? あ,それがScalaなのかな?