Convert tail calls to kotlin
This commit is contained in:
parent
a2940286d5
commit
516603a948
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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()
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue