Kotlin-尝试从Lambda返回包含函数时出现“不允许在此处返回”错误

时间:2019-01-22 19:16:53

标签: kotlin

尝试从lambda返回到封闭函数(foo)时显示错误return is not allowed here

这是怎么回事?我在做错什么吗?

fun bar( baz: () -> Unit ) {

    // Empty function
}

fun foo() : Unit? {

    return null // this works fine

    bar {

        return null // shows error 'return is not allowed here'
    }
}

编辑:

我也尝试过:

...

bar {

    return@bar null
}

...

但这会导致错误Null can not be a value of a non-null type Unit

3 个答案:

答案 0 :(得分:2)

Lambda内不允许使用

return语句。如果要从lambda返回,则应使用标签。

bar {
    return@bar 
}

或者您可以对bar函数使用inline修饰符。

答案 1 :(得分:1)

在Kotlin中有一条规则-return总是从fun返回。可以使用return@<label/function name>从函数或lambda返回。

接下来,出现inline fun。内联函数不是真正的函数,它们内联到调用站点中,因此,可以从作为该函数参数的lambda内部进行返回(标准库中有很多示例)

总结:

inline fun bar(a: () -> Unit) { a() }
fun buz() : Int {
  bar { return 42 } /// such return is only possible to inline fun
  return 10
}
val x = buz() /// will be 42
bar { if (something) return@bar }

这里我们从lambda返回,而不是从函数返回。

答案 2 :(得分:1)

我们都知道 kotlin 规范中的事实。但背后的原因一点也不微不足道。

问题是:为什么在 kotlin 中,默认情况下不允许在 lambda 中返回?

虽然这是一个老问题,但解释可能的原因对我来说仍然很重要。

乍一看,匿名函数和 lambda 的行为几乎相同:无名函数。但是,对于关键字 fun,函数体中允许使用 return,但没有 fun(在 lambda 中)则不允许!不都是“功能”吗?

Lambda 确实是一个函数,但从字面上看,它更像是一个柏拉图式的“表达式”,它最终会以自己的设计意图来表示一个对象,因此实际上并不需要返回。

此外,由于“函数内联”和“非本地返回”功能/语法糖,lambda 中的 return 可能不明确。如果 lambda 是内联的,则返回的词法上下文是“非本地的”,这意味着它终止并从调用者函数返回。但是当它没有内联并且我们允许返回时,我们期望什么行为?这是矛盾和不直观的。

这就是为什么必须提供标签才能在没有内联的情况下在 lambda 中使用 return。当然,我们可以在任何地方使用标签返回,但它只会增加样板工作。