( ꒪⌓꒪) ゆるよろ日記

( ゚∀゚)o彡°オパーイ!オパーイ! ( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

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戦記