为什么不能像在List :: map中那样在Sequence :: map函数中调用Deferred :: await?
我做了一个小例子
fun example() = runBlocking {
val list = listOf(1, 2, 3, 4)
list.map { async { doSomething(it) } }
.map { it.await() }
list.asSequence()
.map { async { doSomething(it) } }
.map { it.await() } // Error: Kotlin: Suspension functions can be called only within coroutine body
}
如您所见,最后一条语句未编译。
答案 0 :(得分:7)
这是因为list.map
是inline fun
,这可能是因为它是一个渴望返回新列表的操作。 inline fun
可以容忍suspend
块,因为它更像是一个宏:它被扩展到调用站点中。只要呼叫站点在suspend
块内,就可以正常工作。
sequence.map
很懒,它只是在从序列中提取项目时向最终将要执行的操作流水线添加另一个lambda。
在可暂停的世界中,最类似于懒惰序列的是通道,但是它改变了编程模型。
答案 1 :(得分:1)
添加到Marko的答案中,这是正确的:
由于序列是惰性的,因此await()
的调用实际上可能在完成runBlocking
之后发生。在您开始将元素从列表中拉出之前,异步调用和等待都不会发生。
在上述代码中,没有任何东西可以将元素拉出序列,因此序列上的任何映射操作都不会在runBlocking
块内发生。