Scala:索引Seq而不是for循环中的List

时间:2015-10-13 06:47:19

标签: scala

以下代码显示了类型不匹配错误:

def f(arr:List[Int]): List[Int] = 
  for(num <- 0 to arr.length-1; if num % 2 == 1) yield arr(num)

据说它找到了IndexedSeq而不是List。以下作品:

def f(arr:List[Int]): List[Int] = 
  for(num <- (0 to arr.length-1).toList; if num % 2 == 1) yield arr(num)

我之前在for循环中使用了i <- a to b但之前没有看到过这个错误。有人可以解释为什么格式i <- a to b不能在这里使用吗?

3 个答案:

答案 0 :(得分:4)

因为0 to arr.length-1返回类型为:IndexedSeq[Int],所以在执行for yield时,它也会产生IndexedSeq[Int]类型的结果。

正确的函数定义:

 def f(arr:List[Int]):IndexedSeq[Int] = for( num <- 0 to arr.length-1 if num%2==1) yield arr(num)

for( num <- 0 to arr.length-1 if num%2==1) yield arr(num) 

将翻译为:

scala> def f(arr:List[Int]) = (0 to arr.length-1).filter(i => i%2==1).map(i => arr(i))
f: (arr: List[Int])scala.collection.immutable.IndexedSeq[Int]

因此我们可以看到返回类型由0 to arr.length-1类型决定。

(0 to arr.length-1).toList正在将返回IndexedSeq[int]类型更改为List[Int]类型,因此for yield将生成类型为List[Int]的结果。

答案 1 :(得分:1)

在scala for中是syntax sugar,其中:

for (i <- a to b) yield func(i)

翻译为:

RichInt(a).to(b).map({ i => func(i) })

RichInt.to返回Range

Range.map返回IndexedSeq

答案 2 :(得分:1)

在Scala中,对于for循环的每次迭代,yield都会生成一个将被记住的值。 返回的集合类型与您迭代的类型相同,因此List生成List,IndexedSeq生成IndexedSeq,依此类推。

(0 to arr.length-1)的类型为scala.collection.immutable.Range,它是scala.collection.immutable.IndexedSeq[Int]的继承。因此,在第一种情况下,结果为IndexedSeq[Int],但函数f的返回类型为List[Int],显然它不起作用。在第二种情况下,List生成一个List,返回类型fList[Int]

您还可以编写函数f,如下所示:

def f(arr: List[Int]): IndexedSeq[Int] = for( a <- 1 to arr.length-1; if a % 2 == 1) yield arr(a)

另一个例子:

scala> for (i <- 1 to 5) yield i
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5)

scala> for (e <- Array(1, 2, 3, 4, 5)) yield e
res1: Array[Int] = Array(1, 2, 3, 4, 5)