作者:莺妈 | 来源:互联网 | 2023-01-04 18:33
我正在尝试编写一个Kotlin函数,它返回一个带参数的lambda.我正在尝试使用以下代码来执行此操作:
fun makeFunc() : (T.() -> Unit) {
return { t: T ->
print("Foo")
}
}
注意:在实际程序中,该功能更复杂并且使用t
.
Kotlin拒绝这个无效,给出了'预期无参数'错误t: T
.
但是,首先将此lambda分配给变量不会被拒绝并且工作正常:
fun makeFunc() : (T.() -> Unit) {
val x = { t: T ->
print("Foo")
}
return x
}
这两个片段看起来完全相同,为什么会这样呢?在将return
语句解释为lambda以外的其他语句之后是花括号吗?
另外,IntelliJ告诉我变量的值可以内联,但这似乎会导致错误.
1> hotkey..:
在Kotlin中,功能类型和lambda表达式的设计有一个奇怪的时刻.
实际上,可以在这两个语句中描述行为:
功能类型的命名值可以在普通功能类型(A, B) -> C
和相应类型的功能之间互换,第一个参数变为接收器A.(B) -> C
.这些类型可以相互分配.
因此,当您声明一个键入的变量时(T) -> Unit
,您可以传递它或在T.() -> Unit
预期的位置使用它,反之亦然.
但是,Lambda表达式不能以这种自由的方式使用.
当一个带接收器的函数T.() -> Unit
被期望时,你不能放置一个参数T
为该位置的lambda,lambda应该与签名完全匹配,接收器和第一个参数不能相互转换:
函数文字参数或函数表达式的形状必须与相应参数的扩展名完全匹配.您不能传递扩展函数文字或扩展函数表达式,其中函数是预期的,反之亦然.如果您确实想这样做,请更改形状,将文字指定给变量或使用as
运算符.
(来自上面链接的文件)
此规则使lambda更易于阅读:它们始终与预期类型匹配.例如,带接收器的lambda和带隐式的lambda之间没有任何歧义it
.
相比:
fun foo(bar: (A) -> B) = Unit
fun baz(qux: A.() -> B) = Unit
val f: (A) -> B = { TODO() }
val g: A.() -> B = { TODO() }
foo(f) // OK
foo(g) // OK
baz(f) // OK
baz(g) // OK
// But:
foo { a: A -> println(a); TODO() } // OK
foo { println(this@foo); TODO() } // Error
baz { println(this@baz); TODO() } // OK
baz { a: A -> println(a); TODO() } // Error
基本上,这是IDE诊断错误.请将其作为错误报告给Kotlin问题跟踪器.