什么是序列理解的类型

时间:2012-07-15 04:11:49

标签: scala for-comprehension

我刚开始学习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
}

这似乎是矛盾的。 让我知道编译类型错误的原因是什么。

2 个答案:

答案 0 :(得分:2)

Luigi的回答是正确的,但可能需要更多解释。运行时类型确实是Vector[Int],但编译器不知道这一点。 for表达式等同于

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

因此它创建一个Range,然后在其上调用filter方法。正如您在API文档中看到的那样,Range的过滤方法被声明为返回IndexedSeq

答案 1 :(得分:1)

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

编辑添加:你会注意到网站上的例子,他们使用List.range方法在for-expression中生成生成器,这就是他们获得返回类型{{1}的方式}。如果您使用List[Int]方法(而不是生成Vector.range的{​​{1}}方法),那么您将过滤until,编译器会将此推断为返回类型。

如果您想查看表达式或函数的类型,REPL会在您定义或评估它时告诉您:

Range