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)

So it creates a Range and then calls the filter method on it. As you can see in the API documentation, the filter method of Range is declared as returning an IndexedSeq.

于 2012-07-15T04:58:41.370 回答
1

您将类与类型混淆了。for 表达式产生的值的类型是IndexedSeq[Int],它恰好由 Vector 实例实现。您在签名中指定返回类型必须是Vector[Int],但 for 表达式没有提供这样的保证。

编辑添加:您会在网站上的示例中注意到,他们使用该List.range方法在 for 表达式中生成生成器,这就是他们获得返回类型的方式List[Int]。如果您使用该Vector.range方法(而不是until产生 a的方法Range),那么您将过滤 aVector并且编译器会将其推断为返回类型。

如果您想查看表达式或函数的类型,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 回答