【Coroutines】Implement Python Generator by Kotlin Coroutines

Expected

a generator object that can generate sequence objects

and only generate object when consumer object request for it

kotlin 复制代码
fun main() {
    val generator = generator {
        yield(100)
        yield(200)
        yield(300)
    }
    while (generator.hasNext()) {
        val value = generator.await()
        println(value)
    }
}
Implementation
kotlin 复制代码
package com.code.kotlin

import kotlin.coroutines.*

@RestrictsSuspension
interface GeneratorScope<T> {

    suspend fun yield(value: T)
}

interface GeneratorIterator<T> : Iterator<T> {

    fun await(): T
}

internal interface Generator<T> : GeneratorScope<T>, GeneratorIterator<T>, Continuation<Any>

internal sealed class GeneratorState<T> {
    class WAITING<T>(val continuation: Continuation<Unit>) : GeneratorState<T>()
    class READY<T>(val continuation: Continuation<Unit>, val value: T) : GeneratorState<T>()
    class COMPLETED<T> : GeneratorState<T>()
}

internal class GeneratorImpl<T> : Generator<T> {

    override val context: CoroutineContext = EmptyCoroutineContext

    internal lateinit var state: GeneratorState<T>

    override suspend fun yield(value: T) {
        suspendCoroutine { continuation ->
            when (val _state = state) {
                is GeneratorState.WAITING -> {
                    state = GeneratorState.READY(continuation, value)
                }
                is GeneratorState.READY,
                is GeneratorState.COMPLETED -> throw IllegalStateException()
            }
        }
    }

    override fun resumeWith(result: Result<Any>) {
        state = GeneratorState.COMPLETED()
    }

    private fun resume() {
        when (val _state = state) {
            is GeneratorState.WAITING -> {
                _state.continuation.resume(Unit)
            }
            else -> {}
        }
    }

    override fun hasNext(): Boolean {
        resume()
        return state !is GeneratorState.COMPLETED
    }

    override fun next(): T {
        when (val _state = state) {
            is GeneratorState.READY -> {
                state = GeneratorState.WAITING(_state.continuation)
                return _state.value
            }
            is GeneratorState.WAITING,
            is GeneratorState.COMPLETED -> throw IllegalStateException()
        }
    }

    override fun await() = next()
}

fun <T> generator(
    block: suspend GeneratorScope<T>.() -> Unit
): GeneratorIterator<T> {
    val generator = GeneratorImpl<T>()
    val continuation = block.createCoroutine(generator, generator)
    generator.state = GeneratorState.WAITING(continuation)
    return generator
}
相关推荐
独好紫罗兰17 分钟前
对python的再认识-基于数据结构进行-a003-列表-排序
开发语言·数据结构·python
AIFarmer24 分钟前
在EV3上运行Python语言——无线编程
python·ev3
不会代码的小测试26 分钟前
UI自动化-POM封装
开发语言·python·selenium·自动化
2401_8414956428 分钟前
【LeetCode刷题】二叉树的层序遍历
数据结构·python·算法·leetcode·二叉树··队列
ZH154558913138 分钟前
Flutter for OpenHarmony Python学习助手实战:GUI桌面应用开发的实现
python·学习·flutter
儿歌八万首39 分钟前
硬核春节:用 Compose 打造“赛博鞭炮”
android·kotlin·compose·春节
B站计算机毕业设计超人44 分钟前
计算机毕业设计Hadoop+Spark+Hive招聘推荐系统 招聘大数据分析 大数据毕业设计(源码+文档+PPT+ 讲解)
大数据·hive·hadoop·python·spark·毕业设计·课程设计
B站计算机毕业设计超人1 小时前
计算机毕业设计hadoop+spark+hive交通拥堵预测 交通流量预测 智慧城市交通大数据 交通客流量分析(源码+LW文档+PPT+讲解视频)
大数据·hive·hadoop·python·spark·毕业设计·课程设计
CodeSheep程序羊1 小时前
拼多多春节加班工资曝光,没几个敢给这个数的。
java·c语言·开发语言·c++·python·程序人生·职场和发展
独好紫罗兰1 小时前
对python的再认识-基于数据结构进行-a002-列表-列表推导式
开发语言·数据结构·python