3

これは奇妙に思えます。以下は正常にコンパイルされます。

def foo(s: String) = "balsh"
def foo(s: String)(s2: String) = "kahsd"

2 番目のパラメーターを暗黙的にしても、問題なくコンパイルされます。

ただし、次の場合はそうではありません。

def foo(s: String) = "bjda"
def foo(s: String)(fun: String => String) = fun(s)

^「オーバーロードされた定義へのあいまいな参照」のためにコンパイルされません。

私の当初の考えでは、Scala が関数を Java に変換する方法が原因で、2 つの署名が同じになるというものでした。ただし、javap を使用してコード化されたコンパイル (2 番目の関数のみ) を見ると、そのような関数は実際には次のように変換されていることがわかります。

public java.lang.String foo(java.lang.String, scala.Function1);

そのため、別の署名を持つ別のメソッドが作成されます。では、なぜこれがコンパイルに失敗するのでしょうか?

さらにややこしいことに、以下は実際に問題なくコンパイルされます。

def foo(s: String) = "bjda"
def foo(s: String, fun: String => String) = fun(s)

関数をパラメータの最初のセットの一部にすれば、すべて問題ありません!

なぜこれが起こっているのか誰にも分かりますか?

編集:

だから私はこれを試しました:

object main {
  def write(s: String) = "sasd"
  def write(s: String)(implicit s2: String => String) = s2(s)
}

単純に、2 番目のパラメーターの関数を暗黙的にしました。ほら、これはコンパイルされます。

これは、生成される Java コードです。

public final class main$ extends java.lang.Object{
    public static final main$ MODULE$;
    public static {};
    public java.lang.String write(java.lang.String);
    public java.lang.String write(java.lang.String, scala.Function1);
}

これは、暗黙のない元のものから私が期待していたものです!

4

2 に答える 2

0

暗黙のハッキングを回避したい場合は、別の方法を次に示します。

def foo(s: String) = "balsh"
def foo(t: String)(s2: String) = "kahsd"

ここで、2 番目の関数のパラメーター名が別のものに変更されます。次に、最初のものが必要な場合:

foo(s = "foo")

2番目が必要な場合:

foo(t = "foo")
于 2015-06-16T01:22:35.230 に答える
0

戻り値の型が実際には異なるだけなので、コンパイラが2つの間で選択する方法はないと思います。関数の戻り値の型に基づいてパラメータのみをディスパッチすることはできません。署名は次のように考えてください。

def foo(s: String): String
def foo(s: String): String => String

暗黙的にするとなぜ機能するのかわかりませんが、同じエラーが発生します(予想どおり)。

def foo(s: String, fun: String => String) 

一方、ディスパッチ可能な別のパラメータリストがあります。

于 2013-08-08T15:24:35.287 に答える