Java 7のクロージャ(BGGA版)のプロトタイプでCurry化とフィボナッチ数
Java 7のクロージャ(BGGA版)のプロトタイプを試してみた - Scalaとか構文解析についてあれこれ書く日記
俺も触ってみたよ。
【コラム】Java API、使ってますか? (54) Java SE 7の要注目機能"クロージャ"はどうなるのか その2 | エンタープライズ | マイナビニュース
上記の情報を元に動作環境を作る。
JDK6が入ってるなら、http://javac.info/closures.tar.gzを落としてきて解凍すれば出来上がり。
まずは、サンプルコードをさらっと動かして感じを掴んだので、Curry化に挑戦する。
Curry化
最初は、任意のクロージャを引数にとって、Curry化されたクロージャを返すようなCurryクロージャを作ろうと思ったのだが、
以下の問題があって断念した。
- 可変長引数をとるようなクロージャを定義できないっぽい
- クロージャ内から自身の引数の型情報(Function Types)を取得する手段がない
なので、汎用的なCurry化クロージャを作るのはあきらめて、こんな感じでやってみた。
import static java.lang.System.out; public class Currying{ public static void main( String [] args ){ // 2数の加算 { int, int => int } plus = { int x, int y => x + y }; // Curry化 { int => { int => int } } curriedPlus = { int x => { int y => x + y } }; out.println( "Normal = " + plus.invoke( 4,5 ) ); out.println( "Curried = " + curriedPlus.invoke(4).invoke(5) ); // 3つの文字列を","で連結する {String,String,String => String} join = { String a , String b , String c => a + "," + b + "," + c}; // Curry化 {String => {String => {String => String }}} curriedJoin = { String a => { String b =>{ String c => a + "," + b + "," + c } } }; out.println( "Normal = " + join.invoke( "hoge","fuge","hige" ) ); out.println( "Curried = " + curriedJoin.invoke("hoge").invoke("fuge").invoke("hige") ); // 2つの引数を固定化 {String => String} curriedJoinHogeFuge = curriedJoin.invoke("hoge").invoke("fuge"); out.println( curriedJoinHogeFuge.invoke( "hoooo") ); out.println( curriedJoinHogeFuge.invoke( "ヒャッハーーー!!") ); } }
フィボナッチ数
次に、フィボナッチ数を計算するクロージャを書いてみる。こんな感じ。
import static java.lang.System.out; public class Fibonatti{ public static void main( String [] args ){ {int => int } fibonatti = { int x => ( x == 0 ? 0 : ( x == 1 ? 1 : fibonatti.invoke( x - 1 ) + fibonatti.invoke( x - 2 ) )) }; for( int i = 0 ; i < 20; i++ ){ out.printf( "fibonatti(%d) = %d\n" ,i, fibonatti.invoke(i) ); } } }
クロージャの中から、自分自身を再帰的に呼び出すことができるので簡単にできる。
このあたりを参考にしましたよ。
カリー化 - Wikipedia
JavaScript で引数束縛: Days on the Moon
フィボナッチ数 - Wikipedia
ラムダ計算 - Wikipedia
Java でラムダ - IT戦記