Kotlin协程:依次调用Deferred :: await :: map

时间:2018-11-25 15:35:14

标签: kotlin coroutine kotlin-coroutines

为什么不能像在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

}

如您所见,最后一条语句未编译。

2 个答案:

答案 0 :(得分:7)

这是因为list.mapinline fun,这可能是因为它是一个渴望返回新列表的操作。 inline fun可以容忍suspend块,因为它更像是一个宏:它被扩展到调用站点中。只要呼叫站点在suspend块内,就可以正常工作。

另一方面,

sequence.map很懒,它只是在从序列中提取项目时向最终将要执行的操作流水线添加另一个lambda。

在可暂停的世界中,最类似于懒惰序列的是通道,但是它改变了编程模型。

答案 1 :(得分:1)

添加到Marko的答案中,这是正确的:

由于序列是惰性的,因此await()的调用实际上可能在完成runBlocking之后发生。在您开始将元素从列表中拉出之前,异步调用和等待都不会发生。

在上述代码中,没有任何东西可以将元素拉出序列,因此序列上的任何映射操作都不会在runBlocking块内发生。