以下代码显示了类型不匹配错误:
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
不能在这里使用吗?
答案 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,返回类型f
为List[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)