Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: Inline lambda and overload resolution ambiguity

I have a simple factory pattern where the implementation is determined through overload resolution. Problem is that the Kotlin compiler complains with "Overload resolution ambiguity.." for the inline lambda.

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

How does the Kotlin compiler resolve overload resolution and why is the inline lambda considered to be ambiguous?

like image 528
Tomas Karlsson Avatar asked Mar 01 '16 20:03

Tomas Karlsson


1 Answers

Kotlin compiler resolves every expression only once. So when compiler starts resolution for lambda expression, it should know types of lambda arguments. Because of this compiler should choose one of methods create before it starts to look inside lambda.

Example:

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

Here we can't choose one of functions foo because no one of them is more specific that another, so we can't start resolution for lambda expression because we don't know type for it.

In your example it is in theory possible to start resolution for lambda before choosing particular function because for all potential functions types of lambda arguments are the same. But it is untrivial logic which might be hard to implement.

like image 65
erokhins Avatar answered Oct 31 '22 08:10

erokhins