9

この例を参照してください。

def hello(a:String, b:String) = println(a + ":" + b)
val m1 = hello("aaa", _ )
m1("bbb")

コンパイルできません。部分メソッドに型を追加する必要があります。

val m1 = hello("aaa", _: String)

なぜscalaはメソッドの2番目のパラメーターが何であるかを知らないのhelloですStringか?

4

3 に答える 3

15

Scalaの型推論はフローベースです。メソッドと関数には、他のタイプを推測するために使用される明示的なパラメータータイプが必要です。パラメータタイプは、メソッドまたは関数本体から推測することはできません。ただし、パラメータタイプが外部コンテキストから認識されているため、ラベルを付ける必要がない場合もあります。2つの例、

val f: String => Unit = hello("aaa", _)
val s = Seq(1,2).map(_+1) // Seq[Int].map expects a function of Int argument type

以下は、たとえばMLやHaskellと比較したScalaの型推論の制限についてのMartinOderskyからの引用です。課題には、Scalaのオーバーロード、レコードの選択、サブタイピング、および物事をシンプルに保つ必要性が含まれます。

ScalaにHindley/Milner型推論がない理由は、オーバーロード(型クラスではなく、アドホックバリアント)、レコード選択、サブタイピングなどの機能と組み合わせることが非常に難しいためです。不可能だと言っているわけではありません。これらの機能を組み込んだ拡張機能はたくさんあります。実際、私はそれらのいくつかを自分自身で巧みに扱ってきました。これを実際にうまく機能させるのは非常に難しいと言っているだけです。実際には、小さな型の式と適切なエラーメッセージが必要です。これもまた、閉ざされたケースではありません。多くの研究者がここで限界を押し上げることに取り組んでいます(たとえば、RemyのMLFを見てください)。しかし、現時点では、これらの機能のより良い型推論とより良いサポートのトレードオフです。両方の方法でトレードオフを行うことができます。

出典:投稿の下のコメントユニバーサル型推論は悪いことです。

于 2011-08-19T18:16:13.353 に答える
4

簡単に言うと、Scalaはパラメーターの種類を使用して適切なメソッドを検索しますが、パラメーターの種類を推測するためにメソッドの種類を使用するのではありません。

必要なことを行うにはhello、2つのパラメーターを使用して、可能なすべての呼び出しを検索する必要があります。最初のパラメーターStringは暗黙の変換を含む可能性があります。次に、最も具体的なオプションが1つ見つかった場合は、それを使用して推測します。その2番目のパラメーターのタイプ。すでに行っていることすべてに加えてこれを行う必要があり、すでにかなり遅いコンパイルであるものをさらに遅くします。不可能ではありませんが、それはできません。

于 2011-08-19T20:53:43.353 に答える
3

これは、過負荷になる可能性があるため、この定義に潜在的なあいまいさが存在するためである可能性がありhelloます。

// inside some class context
def hello(a:String, b:String) = println(a + ":" + b)
def hello(a:String, b:Int) = println(a + ":" + b.toString)
val m1 = hello("aaa", _ ) // which one to choose?

できるのはあなただけではないことを考慮してくださいval m1 = hello("aaa", _)。を実行しているクラスのユーザーがいる可能性がありますval my_hello = (new C).hello("aaa", _)。そして、元の文字列helloメソッドにオーバーロードを追加することで、ソースコードの互換性を破ります。これは、突然、何をすべきかが明確でなくなったためです。

これが唯一の理由かどうかはわかりませんが、安全対策としては確かに見ることができます。

于 2011-08-19T18:04:18.700 に答える