Convert tail calls to kotlin

This commit is contained in:
Mike Cifelli 2018-08-18 09:25:02 -04:00
parent a2940286d5
commit 516603a948
5 changed files with 31 additions and 55 deletions

View File

@ -1,25 +0,0 @@
package recursion;
import java.util.stream.Stream;
@FunctionalInterface
public interface TailCall<T> {
TailCall<T> apply();
default boolean isComplete() {
return false;
}
default T result() {
throw new UnsupportedOperationException();
}
default T invoke() {
return Stream.iterate(this, TailCall::apply)
.filter(TailCall::isComplete)
.findFirst()
.get()
.result();
}
}

View File

@ -0,0 +1,13 @@
package recursion
@FunctionalInterface
interface TailCall<T> {
fun isComplete() = false
fun apply(): TailCall<T>
fun result(): T = throw UnsupportedOperationException()
operator fun invoke() = generateSequence(this) { it.apply() }
.first { it.isComplete() }
.result()
}

View File

@ -1,28 +0,0 @@
package recursion;
public class TailCalls {
public static <T> TailCall<T> tailCall(TailCall<T> nextCall) {
return nextCall;
}
public static <T> TailCall<T> done(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 UnsupportedOperationException();
}
};
}
}

View File

@ -0,0 +1,16 @@
package recursion
object TailCalls {
@JvmStatic
fun <T> tailCall(nextCall: () -> TailCall<T>) = object : TailCall<T> {
override fun apply() = nextCall()
}
@JvmStatic
fun <T> done(value: T) = object : TailCall<T> {
override fun isComplete() = true
override fun result() = value
override fun apply() = throw UnsupportedOperationException()
}
}

View File

@ -8,13 +8,13 @@ class TailCallTest {
@Test @Test
fun `tailCall does not support result`() { fun `tailCall does not support result`() {
val tailCall = TailCall<Any> { null } val tailCall = object : TailCall<Nothing?> { override fun apply() = done(null) }
assertThrows(UnsupportedOperationException::class.java) { tailCall.result() } assertThrows(UnsupportedOperationException::class.java) { tailCall.result() }
} }
@Test @Test
fun `done does not support apply`() { fun `done does not support apply`() {
assertThrows(UnsupportedOperationException::class.java) { done<Any>(null).apply() } assertThrows(UnsupportedOperationException::class.java) { done(null).apply() }
} }
} }