きしだのはてな このページをアンテナに追加 RSSフィード

2014-11-03(月) Java8のLambdaで再帰する

[][]Java8のラムダで再帰する 21:55 Java8のラムダで再帰するを含むブックマーク

宮川さんが、不動点コンビネータを使ってラムダで再帰するエントリ書いてました。

不動点コンビネータを使ってラムダ式で再帰関数を定義する - 宮川拓の日記

型ごとのコンビネータが必要というのは、これはspecializationが導入されるのを待つしかないですね。


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


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

なのでここでCM。

詳しくはまた今度かきます。きっと。

とりいそぎ、著者のひとりである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])

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