在Kotlin中yield(i)是什么意思?

时间:2020-03-17 01:08:55

标签: kotlin kotlin-coroutines

我正在学习Kotlin的协程。

代码A来自https://kotlinlang.org/docs/reference/coroutines/flow.html的文字

yield(i)在科特林语中是什么意思?

代码A

fun foo(): Sequence<Int> = sequence { // sequence builder
    for (i in 1..3) {
        Thread.sleep(100) // pretend we are computing it
        yield(i) // yield next value
    }
}

fun main() {
    foo().forEach { value -> println(value) } 
}

2 个答案:

答案 0 :(得分:2)

这不是协程功能。此代码是与协程流进行比较的示例。序列是用于延迟评估每个元素的迭代器。列表包含所有提前的值,但是序列仅在诸如forEach调用(“终端”序列函数)之类的请求时才计算每个值。

上面的代码只是模拟一个十分之一秒的序列来计算其每个值。它只是产生数字1、2和3。yield()是如何告诉sequence构建器函数产生另一个要使用的值的。

通过sequence构建器函数,您可以传递一个lambda,该lambda一次计算一个值,然后通过调用yield()返回它们。

更常见的是不使用构建器,而是使用toSequence()将某些集合转换为Sequence,然后可以在Sequence上链接类似map的操作,直到对它们进行评估像forEach这样的终端操作被调用。这样可以避免为每个操作分配中间列表。

答案 1 :(得分:0)

sequence中调用yield(something)表示iterator of the Sequence hasNext(),并且在您致电something时会得到next()

迭代器的用户调用next()然后再次调用hasNext()之后,将从yield恢复执行。


当只产生1 2 3时,它看起来毫无意义。但是请考虑进行二叉树遍历。预购,有序或后购都很容易用递归代码编写。我们可以使用调用堆栈来记住下一步该做什么。

当我们想要构建一个迭代器时,我们会失去所有这些好东西。我们必须使用显式堆栈来记住下一个要访问的节点-除非我们使用sequence函数。

same fringe problem是其强大功能的一个例子。


我不同意另一个回答,即“这不是协程功能”。 能够在执行过程中恢复是 co <​​/ strong>例程的定义。将其与必须从头开始运行的 sub 例程进行对比。

我们经常使用“协程”来指代Kotlin中的并发构造。序列构建不是这些的一部分,而是协程的一个例子。