1 つの方法はhelper
、関数と数値を引数として受け取る 2 次関数 を作成してから、実際に必要な関数 を作成することですfact = helper(helper,x)
。
そのようです:
BiFunction<BiFunction, Double, Double> factHelper =
(f, x) -> (x == 0) ? 1.0 : x*(double)f.apply(f,x-1);
Function<Double, Double> fact =
x -> factHelper.apply(factHelper, x);
これは、変更可能な構造への参照をキャプチャするクロージャーのようなコーナーケースのセマンティクスに依存したり、「初期化されていない可能性がある」という警告を表示して自己参照を許可したりするよりも、わずかに洗練されているように思えます。
それでも、Java の型システムのため、これは完全な解決策ではありません。ジェネリックはf
、 への引数がfactHelper
と同じ型factHelper
(つまり、同じ入力型と出力型) であることを保証できません。これは、ジェネリックが無限にネストされるためです。
したがって、代わりに、より安全な解決策は次のようになります。
Function<Double, Double> fact = x -> {
BiFunction<BiFunction, Double, Double> factHelper =
(f, d) -> (d == 0) ? 1.0 : d*(double)f.apply(f,d-1);
return factHelper.apply(factHelper, x);
};
の完全ではないジェネリック型から発生したコードの臭いfactHelper
は、ラムダ内に含まれている (または、あえて言うならカプセル化されている) ため、factHelper
知らないうちに が呼び出されることはありません。