当试图返回内联lambda时,Kotlin“预计没有参数”

我试图写一个Kotlin函数返回一个lambda采取参数。 我试图使用下面的代码来做到这一点:

fun  makeFunc() : (T.() -> Unit) { return { t: T -> print("Foo") } } 

注意:在实际的程序中,function比较复杂,使用t

Kotlin认为这是无效的,在t: T给出了’Expected no parameters’错误。

但是,首先将这个lambda赋值给一个variables不会被拒绝,并且工作正常:

 fun  makeFunc() : (T.() -> Unit) { val x = { t: T -> print("Foo") } return x } 

这两个片段似乎是相同的,为什么这是这种情况? return语句之后的花括号是否被解释为lambda之外的东西?

此外,IntelliJ告诉我,variables的值可以内联,而这似乎导致错误。

在这里输入图像说明

在Kotlin的函数types和lambdaexpression式的设计中有一个好奇的时刻。

其实这种行为可以用这两种说法来描述:

  • (A, B) -> C的函数types的命名值在第一个参数变成接收器A.(B) -> C可以互换。 这些types可以相互分配 。

    所以,当你声明一个types为(T) -> Unit的variables时,你可以传递它,或者在T.() -> Unit是预期的地方使用它,反之亦然。

  • 但是,Lambdaexpression式不能以这种自由的方式使用。

    当一个带有接收者T.() -> Unit的函数被期望的时候,你不能把一个带有参数T的lambda放在那个位置,lambda应该和签名完全匹配,接收者和第一个参数不能相互转换:

    函数文字参数或函数expression式的形状必须与相应参数的扩展名完全匹配。 你不能传递一个扩展函数字面量或扩展函数expression式的地方,反之亦然。 如果你真的想这样做,改变形状,分配文字到一个variables或使用as运算符。

    (来自上面链接的文件 )

    这个规则使得lambda更容易阅读:它们总是匹配预期的types。 例如,在一个带有接收器的lambdaexpression式和一个带有隐式lambdaexpression式的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问题跟踪程序的错误。

你正在接收器T上定义一个函数type () -> Unit ,实际上这个函数没有参数,参见"()" 。 错误是有道理的。 既然你定义了T作为接收者的函数types,你可以参考T

 fun  makeFunc(): (T.() -> Unit) { return { print(this) } }