Java8のラムダで再帰する

宮川さんが、不動点コンビネータを使ってラムダで再帰するエントリ書いてました。
不動点コンビネータを使ってラムダ式で再帰関数を定義する - 宮川拓の日記
型ごとのコンビネータが必要というのは、これはspecializationが導入されるのを待つしかないですね。


「念のため、これはきわめて効率の悪い方法です」ということで、とりあえず、ラムダで再帰する効率の悪くない方法を書いておきます。


とはいえ、一度自分で試してみたほうがいいと思います。
なのでここでCM。

Javaエンジニア養成読本 [現場で役立つ最新知識、満載!] (Software Design plus)

Javaエンジニア養成読本 [現場で役立つ最新知識、満載!] (Software Design plus)

詳しくはまた今度かきます。きっと。
とりいそぎ、著者のひとりであるkikutaroさんの紹介エントリを貼っておきますね。
Javaエンジニア養成読本が出ます! - Challenge Java EE !
CMここまで。


ラムダで再帰する効率の悪くない方法、できましたか?
こういう、変数の制約から逃げる場合は配列を使えばいいですね。
こんな感じになります。

IntUnaryOperator[] fib = new IntUnaryOperator[1];
fib[0] = n -> n <= 1 ? 1 : 
        (fib[0].applyAsInt(n - 1) + fib[0].applyAsInt(n - 2));
IntStream.range(0, 10).forEach(i -> {
    System.out.println(fib[0].applyAsInt(i));
});


Stream中で定義することもできます。

IntStream.range(0, 10)
    .mapToObj(i -> new IntUnaryOperator[i + 1])
    .mapToInt(op -> (op[0] = n -> n <= 1 ? 1:
            (op[0].applyAsInt(n - 2) + (op[0].applyAsInt(n - 1)))).applyAsInt(op.length - 1))
    .forEach(System.out::println);


ここで、次の行は、IntUnaryOperatorの配列とパラメータの値を渡したいのですけど、気軽に使えるタプルがないので、ここでは配列の長さをパラメータ代わりにしてます。

.mapToObj(i -> new IntUnaryOperator[i + 1])

よい子は実コードでマネしないでくださいね。