我正在尝试编写一个Kotlin函数,它返回一个带参数的lambda . 我正在尝试使用以下代码来执行此操作:
fun <T> makeFunc() : (T.() -> Unit) {
return { t: T ->
print("Foo")
}
}
注意:在实际程序中,函数更复杂并使用 t
.
Kotlin拒绝此作为无效,在 t: T
给出'Expected no parameters'错误 .
但是,首先将此lambda分配给变量不会被拒绝并且工作正常:
fun <T> makeFunc() : (T.() -> Unit) {
val x = { t: T ->
print("Foo")
}
return x
}
这两个片段看起来完全相同,为什么会这样呢?在将 return
语句解释为lambda以外的其他语句后,是否大括号?
另外,IntelliJ告诉我变量的值可以内联,但这似乎会导致错误 .
2 回答
在Kotlin中,功能类型和lambda表达式的设计有一个奇怪的时刻 .
实际上,可以在这两个语句中描述行为:
(A, B) -> C
)和相应类型的功能之间互换,第一个参数变为接收器A.(B) -> C
. 这些类型是assignable from each other .因此,当您声明一个类型为
(T) -> Unit
的变量时,您可以传递它或在需要T.() -> Unit
的地方使用它,反之亦然 .但是,
当一个带有接收器
T.() -> Unit
的函数被预期时,你不能在该位置放置一个参数为T
的lambda,lambda应该与签名完全匹配,接收器和第一个参数不能相互转换:(来自上面链接的文件)
此规则使lambda更易于阅读:它们始终与预期类型匹配 . 例如,带接收器的lambda和带有隐式
it
的lambda之间没有任何歧义 .相比:
基本上,这是IDE诊断错误 . 请report it作为Kotlin问题跟踪器的错误 .
您正在接收器
T
上定义函数类型() -> Unit
,该函数确实没有参数,请参阅"()"
. 这个错误很有意义 . 由于您使用T
作为接收器定义了函数类型,因此可以通过this
引用T
: