Java 7のクロージャ
Closures for the Java Programming Language (aka BGGA)でJava 7で実装予定のクロージャが公開されています。ってなわけで軽く試してみました。
環境準備
まずはクロージャを利用したコードをコンパイル&実行するための環境作り。といっても簡単で
- Closures for the Java Programming Language (aka BGGA)で公開されているhttp://www.javac.info/closures.tar.gzを展開
- 展開後のディレクトリ/binをPATHに通す
- %JAVA_HOME%/binより前に来るように注意する
だけです。
クロージャを使ってみる
{引数 => 戻り値}
という型になります。んで中身を定義するときは
{ String hoge => String message = "hello, " + hoge; // 処理 return message; // 戻り値 }
ってな感じ。実際のコードはこうかな。
import java.util.*; public class Sample { // クロージャ内から定数が見れるか public static final String BAZ = "baz"; public static void main(String[] args){ String[] strs = {"hoge", "fuga"}; // クロージャを持つリスト。クロージャは引数がString、戻り値がvoid List<{ String => void }> closures = new ArrayList<{ String => void }>(); // str1はクロージャのスコープ外で定義された変数 // クロージャ内から参照しているため、@Sharedを入れないとコンパイルで警告が出る @Shared String str1; // str2はクロージャ毎の変数 for (String str2 : strs) { str1 = str2; // クロージャを定義 closures.add({ String param => System.out.println(BAZ + ":" + str1 + ":" + str2 + ":" + param); }); } for ({ String => void } closure : closures) { closure.invoke("foo"); } } }
こいつを実行すると
C:\temp\work>java Sample baz:fuga:hoge:foo baz:fuga:fuga:foo
と表示されます。
ポイントは、for文で繰り返すたびに変数定義されるstr2は各クロージャ毎の変数になるけど、for文の外で定義されたstr1は全てのクロージャから参照される変数だってところ。なのでstr1を参照するとどのクロージャも同じ値を参照しています。うーん、どうにも慣れない。
正直クロージャは皆が分かるような仕様じゃないし、利用した方が良い場面も少なそう(GUI系のイベント登録とか?)なのであんまり使うことはないかなぁ、と。自前でライブラリとか作るときは便利かもしれないけど。