3

Scalaを学び始めたばかりです。

http://www.scala-lang.org/node/111の例で遊んでいたときに、型に問題があることがわかりました。

object Main extends App {
  def even(from: Int, to: Int): Vector[Int] =
    for (i <- from until to if i % 2 == 0) yield i

  Console.println(even(0, 20).getClass())
}

これは、次のエラーでコンパイルされません。

<console>:9: error: type mismatch;
 found   : scala.collection.immutable.IndexedSeq[Int]
 required: Vector[Int]
           for (i <- from until to if i % 2 == 0) yield i
                  ^

ただし、戻り値の型指定がなくても動作し、クラスは Vector です。

object Main extends App {
  def even(from: Int, to: Int) =
    for (i <- from until to if i % 2 == 0) yield i

  Console.println(even(0, 20).getClass()) // => class scala.collection.immutable.Vector
}

これは矛盾しているようです。コンパイル型エラーの原因を教えてください。

4

2 に答える 2

2

ルイージの答えは正しいですが、もう少し説明が必要かもしれません。実行時の型は確かVector[Int]に ですが、コンパイラはこれを知りません。for 式は次と同等です。

from.until(to).filter(_%2==0)

そのため、Range を作成し、その上で filter メソッドを呼び出します。API ドキュメントでわかるように、 の filter メソッドはRangeを返すように宣言されていIndexedSeqます。

于 2012-07-15T04:58:41.370 に答える
1

クラスと型を混同しています。for 式によって生成される値の型は ですIndexedSeq[Int]。これはたまたま Vector インスタンスによって実装されています。戻り値の型が でなければならないことを署名で指定しましたVector[Int]が、for 式はそのような保証を与えません。

編集して追加: Web サイトの例で、メソッドを使用して for 式でジェネレーターを生成していることに気付くでしょう。List.rangeそれが、戻り値の型を取得する方法ですList[Int]。( a を生成するメソッドでVector.rangeはなく) メソッドを使用する場合、 a をフィルタリングし、コンパイラはこれを戻り値の型として推論します。untilRangeVector

式または関数の型を確認したい場合、REPL は、定義または評価するときに通知します。

scala> def even(from: Int, to: Int) =
     |   for (i <- from until to if i % 2 == 0) yield i
even: (from: Int, to: Int)scala.collection.immutable.IndexedSeq[Int]
                       // ^ here!
于 2012-07-15T04:53:43.260 に答える