package com.keysking.demo
import java.lang.IllegalStateException
import java.lang.IndexOutOfBoundsException
import kotlin.coroutines.*
fun main() {
val nums = generator { start: Int ->
for (i in 0..5) {
yield(start + i)
}
}
val seq = nums(10)
for (j in seq) {
println(j)
}
}
interface Generator<T> {
operator fun iterator(): Iterator<T>
}
class GeneratorImpl<T>(private val block: suspend GeneratorScope<T>.(T) -> Unit, private val parameter: T) :
Generator<T> {
override fun iterator(): Iterator<T> {
return GeneratorIterator(block, parameter)
}
}
sealed class State {
class NotReady(val continuation: Continuation<Unit>) : State()
class Ready<T>(val continuation: Continuation<Unit>, val nextValue: T) : State()
object Done : State()
}
class GeneratorIterator<T>(private val block: suspend GeneratorScope<T>.(T) -> Unit, private val parameter: T) :
GeneratorScope<T>(), Iterator<T>, Continuation<Any?> {
override val context: CoroutineContext = EmptyCoroutineContext
private var state: State
init {
val coroutineBlock: suspend GeneratorScope<T>.() -> Unit = { this.block(parameter) }
val start = coroutineBlock.createCoroutine(this, this)
state = State.NotReady(start)
}
override suspend fun yield(value: T) = suspendCoroutine<Unit> { continuation ->
state = when (state) {
is State.NotReady -> State.Ready(continuation, value)
is State.Ready<*> -> throw IllegalStateException("Cannot yield a value while ready.")
State.Done -> throw IllegalStateException("Cannot yield a value while done.")
}
}
private fun resume() {
when (val currentState = state) {
is State.NotReady -> currentState.continuation.resume(Unit)
}
}
override fun hasNext(): Boolean {
resume()
return state != State.Done
}
override fun next(): T {
return when (val currentState = state) {
is State.NotReady -> {
resume()
return next()
}
is State.Ready<*> -> {
this.state = State.NotReady(currentState.continuation)
(currentState as State.Ready<T>).nextValue
}
State.Done -> throw IndexOutOfBoundsException("No value left.")
}
}
override fun resumeWith(result: Result<Any?>) {
state = State.Done
result.getOrThrow()
}
}
abstract class GeneratorScope<T> internal constructor() {
abstract suspend fun yield(value: T)
}
fun <T> generator(block: suspend GeneratorScope<T>.(T) -> Unit): (T) -> Generator<T> {
return { parameter ->
GeneratorImpl(block, parameter)
}
}
Last modification:February 18th, 2020 at 09:35 pm
© 允许规范转载
你的文章让我感受到了无尽的欢乐,谢谢分享。 http://www.55baobei.com/eJoNOOTZke.html
《青韵尘梦(限定版)》连续剧高清在线免费观看:https://www.jgz518.com/xingkong/166962.html