1

Scala REPL ではSeq[String]()、 type のパラメーターのデフォルト値として使用できますSeq[T]

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def d[T](foo: Seq[T] = Seq[String]()) = 12
d: [T](foo: Seq[T])Int

scala> d()
res0: Int = 12

IDEA で同じことを試してみると、「Seq[String] が期待される型 Seq[T] に準拠していません」というエラーが表示されます。なんで?

パラメーターのデフォルト値の型の問題について不平を言っている IDEA のスクリーンショット

  • IntelliJ IDEA 2016.2.4
  • Scala プラグイン 2016.2.1
  • スカラ 2.11.7

注 1: 申し訳ありませんが、私の例の関数があまり意味をなさないことはわかっています。ただし、私の実際の (そして便利な) 関数は、ここに投稿するには不必要に複雑です。

注 2: 最初は、この例の型名は型TではなくAnyでしたが、これは良い考えではなく (scala.Any を隠しているため)、混乱を招きました。したがって、私はそれを修正しました。

4

1 に答える 1

1

あなたが言うときdef d[Any]Anyここは一般的なプレースホルダーです。Anyscalaのクラスを指していません。基本Any的に、scala でグローバルに定義されたクラスをシャドウします。Seq[String]したがって、 Seqに代入すると、コンパイラはと[Any]の間の関係を認識しません。一般的なプレースホルダーとして、任意の文字/単語に置き換えることができることに注意してください。結果は同じです。StringAnyAny

これがなぜ REPL で機能するのかというSeq[String]と、デフォルト値として与えられた場合に REPL がなぜそれを受け入れるのか正確にはわかりませんが、メソッド本体内で同じ操作を行うと、repl でエラーを再現できました。

REPL の次のコードはエラーをスローします。

def d[Any](foo: Seq[Any]) = {
  val a: Seq[Any] = Seq[String]()
}
<console>:12: error: type mismatch;
found   : Seq[String]
required: Seq[Any]
       val a: Seq[Any] = Seq[String]()
                                    ^

デフォルトの引数として指定されているときに REPL がエラーをキャッチできなかった理由がわかりません。

代替理論の 1 つは、一般に、ジェネリックを使用する場合、型の値は呼び出し元に基づいて決定されるというものです。例えば、

def d[A](a:A) = {}
d(1) // Type of A is Int
d("a") // Type of A is String

したがって、デフォルト値を指定すると、Stringtoの値が代入されAnyます。Intellij の Type Checker は最初の理論に基づいて動作し、エラーを表示します。しかし奇妙なことに、誰かが先に指摘したように、コンパイルは成功します。

于 2016-10-20T08:20:43.280 に答える