为什么Scala编译器在可变列表上应用foreach时抛出IndexOutOfBoundException

前端之家收集整理的这篇文章主要介绍了为什么Scala编译器在可变列表上应用foreach时抛出IndexOutOfBoundException前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有以下代码.

import scala.collection.mutable.MutableList
val x = MutableList[Int]()
(1 to 10).foreach(x+=1)

我得到java.lang.IndexOutOfBoundsException:1错误.

但,

(1 to 10).foreach(println) this does not throw any error.

indexOutOfBoundException可以通过使用lambda运算符来解决,如下所示:

(1 to 10).foreach(_ => x+=1)

这一切都很好.

我的问题是:
1.为什么我需要在第一种情况下使用lambda运算符而不像第二种情况?
2.为什么编译器抛出IndexOutOfBoundException,我想这不是这个Exception的正确上下文.

解决方法

会发生什么事情是图书馆中的一些小便利,它们会帮你咬人.

foreach签名是

def foreach(f: A => Unit): Unit

在你的情况下,A是Int,所以它需要一个函数,它接受一个I​​nt并返回Unit.与println很好.请注意,您刚刚编写了println,而不是println(某物),这不是一个函数.

人们会期望x = 1只是一个指令,因此它将具有类型Unit,而不是函数,而不是foreach的有效参数,并且会得到一个有用的编译时错误.但是,MutableList中的=实际上返回了列表,这很方便,因为它使链接操作更容易:

def +=(elem: A): this.type

所以x = 1的类型是MutableList [Int].人们仍然期望编译错误,而不是函数.除了MutableLists(实际上所有Seqs)都是函数,使用Int参数,返回Seq元素的类型.该函数只返回第i个元素.同样,这可能很方便,您可以简单地传递期望函数的seq,而不必写入i => SEQ(i)中.现在你有了一个带有Int参数的函数,它是foreach所期望的.

不过,它不会返回Unit,而是Int.但是,scala会接受它作为Int =>单位,只是丢弃价值.所以它编译.

现在做它的作用:首先,它评估foreach中的参数,因此它调用x = 1,得到列表x,现在包含一个元素.然后它将调用函数,该函数是对参数范围从1到10的第i个元素的访问.这样做,它不会向列表添加值,而只是访问给定索引处的元素.然后它立即失败,因为列表只包含一个元素,索引为0,因此使用1调用会抛出IndexOutOfBoundException.

猜你在找的Scala相关文章