4

鉴于一些

suspend fun a(): Int 

这有效:

launch(Unconfined) {
    (1..10).forEach {
        val a = a()
        println("Result is $a")
    }
}

但这在编译时失败:

val action: (Int) -> Unit = {
    // Suspend function should be called only from a coroutine
    // or another suspend function:
    val a = a()
    println("Result is $a")
}
launch(Unconfined) {
    (1..10).forEach(action)
}

此外,它无法修复,因为:

val action: suspend (Int) -> Unit = {
    val a = a()
    println("Result is $a")
}
launch(Unconfined) {
    // suspend (Int) -> Unit cannot be applied to (T) -> Unit
    (1..10).forEach(action)
}

就静态类型系统而言,这里的故事是什么?当前情况看起来像是一个快速破解,其中包含suspend fun调用的内联块仍被推断为非挂起类型签名。

这是一个在最终确定之前需要改进设计的领域吗?

4

1 回答 1

5

函数类型和普通函数类型不是彼此的suspend子类型,因此不能分配或传递给函数来代替彼此:

val f: () -> Unit = { }
val g: suspend () -> Unit = f // Type mismatch

val f: suspend () -> Unit = { }
val g: () -> Unit = f // Type mismatch

这就是为什么 asuspend (Int) -> Unit不能传递给forEach.

基本上,仅在其他挂起函数中调用挂起函数的限制与类型系统无关。这样的调用应该简单地放在一个挂起函数或一个挂起 lambda 或内联到一个中。所以,这也应该有效:

val action: suspend (Int) -> Unit = {
    val a = a()
    println("Result is $a")
}
launch(Unconfined) {
    (1..10).forEach { action() } // The call is inlined into a suspend lambda
}

我也提交了一个关于支持的问题(1..10).forEach(action)KT-22186

于 2018-01-07T22:15:44.443 回答