Java8 ラムダ式で再帰処理

宮川さんときしださんがラムダ式で再起関数を実装する面白いエントリーを書かれていたので自分でも考えてみました。

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

Java8のラムダで再帰する - きしだのはてな

まず、クラス変数で定義するなら再帰は可能です。

public class Test {
    private static IntUnaryOperator fib;
    static {
        fib = (n -> n <= 1
                ? 1
                : (fib.applyAsInt(n - 2) + fib.applyAsInt(n - 1)));
    }

    public static void main(String[] args) throws Exception {
        IntStream.range(0, 10)
            .map(fib::applyAsInt)
            .forEach(System.out::println);
    }
}

main関数内でも定義できますが、この場合はstatic内がやはりいいかなと。
インスタンス変数ならコンストラクタで。

ただし1行で書くとエラーになります。

private static IntUnaryOperator fib =
        (n -> n <= 1
            ? 1
            : (fib.applyAsInt(n - 2) + fib.applyAsInt(n - 1)));
=> コンパイルエラー

他にはFunctionalInterfaceを用意して、パラメータで自分自身を渡すとか。

public class Test {
    public static void main(String[] args) throws Exception {
        Fibonacci fib = ((n, f) -> n <= 1
                ? 1
                : (f.apply(n - 2, f) + f.apply(n - 1, f)));

        IntStream.range(0, 10)
            .map(n -> fib.apply(n, fib))
            .forEach(System.out::println);
    }
}

@FunctionalInterface
interface Fibonacci {
    public int apply(int i, Fibonacci fib);
}

でもこれって再帰と呼んでいいのかどうか?(笑)