Kotlin:内联lambda和重载分辨率模糊

Tom*_*son 10 lambda overload-resolution kotlin

我有一个简单的工厂模式,其中的实现是通过重载决定来确定的.问题是Kotlin编译器抱怨内联lambda的"Overload resolution ambiguity ..".

class Foo(){
    companion object Factory {
        fun create(x: Int, f: (Int) -> Double) = 2.0
        fun create(x: Int, f: (Int) -> Int) = 1
    }
}

fun main(args:Array<String>){
    val a =  Foo.create(1,::fromDouble) //OK
    val b =  Foo.create(1,::fromInt)  //OK
    val ambiguous =  Foo.create(1){i -> 1.0}  //Overload resolution ambiguity?
}


fun fromDouble(int:Int)  = 1.0
fun fromInt(int:Int)  = 1
Run Code Online (Sandbox Code Playgroud)

Kotlin编译器如何解决重载解析,为什么内联lambda被认为是不明确的?

小智 5

Kotlin编译器只解析每个表达式一次.因此,当编译器开始解析lambda表达式时,它应该知道lambda参数的类型.因为这个编译器应该create 在开始查看lambda 之前选择一个方法.

例:

fun foo(f: (Int) -> Int) = 1
fun foo(f: (String) -> String) = ""
val bar = foo { 
   println(it) 
   5
}
Run Code Online (Sandbox Code Playgroud)

在这里我们不能选择其中一个函数,foo因为它们中没有一个比另一个更具体,所以我们无法启动lambda表达式的解析,因为我们不知道type for it.

在您的示例中,理论上可以在选择特定函数之前启动lambda的解析,因为对于所有潜在函数,lambda参数的类型都是相同的.但这可能很难实现,这是非常重要的逻辑.

  • 这是一个无赖。lambda 上的重载分辨率对于数值应用非常有用。假设我有一个处理 float、double 和 int 的矩阵类。使用“重载分辨率”实例化将是 `val ms = Mat44{i,j -&gt; 1.0}` ,现在我被迫将 `val ms = Mat44({i:Int,j:Int -&gt; 1.0} 写成 ( Int,Int) -&gt; Double )` 对于这样一个微不足道的任务来说,这只是简单而愚蠢的冗长。非常感谢@erokhins 的精彩解释! (2认同)