I am trying to lambda Java8 lambda expressions, Wherein I came across this example. I am unable to understand the program flow,
The the below example when the factorialTailRec(1, 5).invoke() statement is called the program flow is as shown below:
The program first goes to the factorialTailRec method and once and checks if the number value is equal to 1. In the first iteration, it's not so it goes to the else part.
In the else block the flow is redirected towards the call method inside the TailCall class which will return the same object.
Now the invoke method is called and then the Stream object tries to iterate through the result. I am not getting how the factorialTailRec is called again? They say its because of the below statement,
TailCall::apply
But, I am not understanding how that is happening.?
public class Factorial {
public static TailCall<Integer> factorialTailRec(
final int factorial, final int number) {
if (number == 1)
return done(factorial);
else
return call(() -> factorialTailRec(factorial * number, number - 1));
}
public static int factorial(final int number) {
return factorialTailRec(1, number).invoke();
}
public static void main(final String[] args) {
System.out.println("//" + "START:FACTTAILREC_DISPLAY_5_OUTPUT");
System.out.println(factorialTailRec(1, 5).invoke());
System.out.println("//" + "END:FACTTAILREC_DISPLAY_5_OUTPUT");
}
}
@FunctionalInterface
public interface TailCall<T> {
TailCall<T> apply();
default boolean isComplete() { return false; }
//...
default T result() { throw new Error("not implemented"); }
default T invoke() {
return Stream.iterate(this, TailCall::apply)
.filter(TailCall::isComplete)
.findFirst()
.get()
.result();
}
}
public class TailCalls {
public static <T> TailCall<T> call(final TailCall<T> nextCall) {
return nextCall;
}
public static <T> TailCall<T> done(final T value) {
return new TailCall<T>() {
@Override public boolean isComplete() { return true; }
@Override public T result() { return value; }
@Override public TailCall<T> apply() {
throw new Error("not implemented");
}
};
}
}