One way is to write a secondary function, helper
, which takes a function and a number as arguments, and then write the function you actually want, fact = helper(helper,x)
.
Like so:
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);
This seems to me to be slightly more elegant than relying on corner case semantics like a closure that captures a reference to a mutable structure, or allowing self-reference with a warning of the possibility of "might not be initialized."
Still, it's not a perfect solution because of Java's type system -- the generics cannot guarantee that f
, the argument to factHelper
, is of the same type as factHelper
(i.e. same input types and output types), since that would be an infinitely nested generic.
Thus, instead, a safer solution might be:
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);
};
The code smell incurred from factHelper
's less-than-perfect generic type is now contained (or, dare I say, encapsulated) within the lambda, ensuring that factHelper
will never be called unknowingly.