2016-03-01 12 views
9

私は実装が過負荷解決によって決定される単純な工場パターンを持っています。問題は、Kotlinコンパイラがインラインラムダの「オーバーロード解決のあいまいさ」と不平を言うことです。Kotlin:インラインラムダとオーバーロード解決のあいまいさ

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 

Kotlinコンパイラは過負荷解決をどのように解決し、インラインラムダは曖昧であると考えられますか?

+4

ラムダを '{i:Int - > 1.0}(Int) - > Double'のようにキャストしてもあいまいさはありませんが、キャストは必要ないと言われているので、これはバグです。また、ラムダを 'val l = {i:Int - > 1.0}'に抽出して使用すると、やはりあいまいさはありません。この問題のバグトラッカーを探してください。新しいバグトラッカーを見つけてください:https://youtrack.jetbrains.com/issues/KT – hotkey

+1

もう一つ興味深いのは、@hotkeyのようにラムダをキャストすると、IDEがあなたはそれが必要ではないことをあなたに伝えます。しかし、あなたがそれを削除した瞬間、それはあいまいさについて不平を言う。 –

+1

ありがとう!おそらくバグだったと考えています。 https://youtrack.jetbrains.com/issue/KT-11265 –

答えて

4

Kotlinコンパイラはすべての式を1回だけ解決します。 コンパイラがラムダ式の解決を開始するとき、lambda引数の型を知る必要があります。 このコンパイラは、createのいずれかを選択してからの前にラムダを調べ始める必要があります。

例:

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

ここではそれらの誰もが他のものより具体的ではありませんので、我々は機能fooのいずれかを選択することはできませんので、我々は知らないので、我々はラムダ式の解像度を起動することはできません。 itを入力します。

あなたの例では、特定の関数を選択する前にラムダの解決を開始することは理論上可能です。潜在的なすべての関数については、ラムダ引数の型は同じです。しかし、それは実装するのが難しいかもしれない珍しいロジックです。

+0

で報告書を提出しました。ラムダのオーバーロード分解能は、数値アプリケーションに非常に便利です。私はfloat、double、intで動作する行列クラスを持っているとしましょう。 "valms = Mat44 {i、j - > 1.0}"となるので、val ms = Mat44({i:Int、j:Int - > 1.0}を( Int、Int) - > Double) 'のような些細な作業のために冗長で冗長です。素晴らしい説明のために多くのおかげさま@erokhins! –

+0

回避策として、 'fun Mat44Int2Double(f:(Int、Int) - > Double)= Mat44(f)'という名前の異なる関数を作成することができます。しかし、それはエレガントではありません... – erokhins

+0

うん、良い古いANSI Cの日を思い出させるようなもの:) –

関連する問題