宮川さんが、不動点コンビネータを使ってラムダで再帰するエントリ書いてました。
不動点コンビネータを使ってラムダ式で再帰関数を定義する - 宮川拓の日記
型ごとのコンビネータが必要というのは、これはspecializationが導入されるのを待つしかないですね。
「念のため、これはきわめて効率の悪い方法です」ということで、とりあえず、ラムダで再帰する効率の悪くない方法を書いておきます。
とはいえ、一度自分で試してみたほうがいいと思います。
なのでここでCM。
Javaエンジニア養成読本 [現場で役立つ最新知識、満載!] (Software Design plus)
- 作者: きしだなおき,のざきひろふみ,吉田真也,菊田洋一,渡辺修司,伊賀敏樹
- 出版社/メーカー: 技術評論社
- 発売日: 2014/11/11
- メディア: 大型本
- この商品を含むブログ (9件) を見る
詳しくはまた今度かきます。きっと。
とりいそぎ、著者のひとりである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])
よい子は実コードでマネしないでくださいね。