我刚开始学习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
}
这似乎是矛盾的。 让我知道编译类型错误的原因是什么。
答案 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