Skip to content

Instantly share code, notes, and snippets.

@mkrzywanski
Created February 15, 2020 15:36
Show Gist options
  • Save mkrzywanski/3a1969eb2cf366696e2038186d023c62 to your computer and use it in GitHub Desktop.
Save mkrzywanski/3a1969eb2cf366696e2038186d023c62 to your computer and use it in GitHub Desktop.
@FunctionalInterface
public interface TailCall<T> {
static <S> TailCall<S> done(S result) {
return new TailCall<S>() {
@Override
public TailCall<S> apply() {
throw new IllegalStateException("Last tailCall does not support apply method");
}
@Override
public boolean isDone() {
return true;
}
@Override
public S result() {
return result;
}
};
}
static <S> TailCall<S> invoke(final TailCall<S> tailCall) {
TailCall<S> tailCallStage = tailCall;
while (!tailCallStage.isDone()) {
tailCallStage = tailCallStage.apply();
}
return tailCallStage;
}
TailCall<T> apply();
default boolean isDone() {
return false;
}
default T result() {
throw new IllegalStateException("Intermediate tailCall does not have any result");
}
}
class Factorial {
public static TailCall<Long> factorial(long n) {
return factorial(n, n - 1);
}
private static TailCall<Long> factorial(long fact, long n) {
if (n == 0 || n == 1) {
return TailCall.done(fact);
} else {
return () -> factorial(fact * n, n - 1);
}
}
}
class Test {
public static void main(String[] args) {
Long result = TailCall.invoke(Factorial.factorial(2)).result();
System.out.println("Result " + result);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment