为什么 Scala 编译器在可变列表上应用 foreach 时抛出 IndexOutOfBoundException
Why Scala compiler throws IndexOutOfBoundException while applying foreach on a mutable list
我有以下代码。
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,我想这不是这个异常的正确上下文。
发生的事情是图书馆里的一些小便利设施密谋咬你一口。
foreach 签名是
def foreach(f: A => Unit): Unit
在你的例子中,A
是 Int
,所以它需要一个接受 Int 和 returns Unit 的函数。 println
没问题。请注意,您刚刚写的是 println
,而不是 println(something)
,这不是一个函数。
人们会期望 x += 1 只是一条指令,所以它的类型是 Unit
,而不是函数,不是 foreach 的有效参数,并且会得到有用的编译时错误.但是 MutableList
中的 +=
实际上是 returns 列表,这很方便,因为它使链接操作更容易:
def +=(elem: A): this.type
所以x+= 1的类型是MutableList[Int]。人们仍然会期待编译错误,而不是函数。除了 MutableList
s(实际上所有 Seq
s)都是函数,带有 Int 参数,返回 Seq 元素的类型。该函数只是 returns 第 i 个元素。同样,这可能很方便,您可以简单地在需要函数的地方传递 seq,而不必编写 i => seq(i)
。现在你有了一个函数,它有一个 Int 参数,这是 foreach 所期望的。
不过,它不是returns单位,而是整数。但是,scala 会将其作为 Int => Unit
接受,只是丢弃该值。所以它编译。
现在来看它的作用:首先,它计算 foreach 中的参数,因此它调用 x+=1
,获取列表 x,它现在包含一个元素。然后它会调用这个函数,它是访问第 i 个元素,参数范围从 1 到 10)。这样做,它不会向列表中添加值,而只是访问给定索引处的元素。然后它立即失败,因为列表只包含一个元素,位于索引 0
,因此使用 1
调用会抛出 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,我想这不是这个异常的正确上下文。
发生的事情是图书馆里的一些小便利设施密谋咬你一口。
foreach 签名是
def foreach(f: A => Unit): Unit
在你的例子中,A
是 Int
,所以它需要一个接受 Int 和 returns Unit 的函数。 println
没问题。请注意,您刚刚写的是 println
,而不是 println(something)
,这不是一个函数。
人们会期望 x += 1 只是一条指令,所以它的类型是 Unit
,而不是函数,不是 foreach 的有效参数,并且会得到有用的编译时错误.但是 MutableList
中的 +=
实际上是 returns 列表,这很方便,因为它使链接操作更容易:
def +=(elem: A): this.type
所以x+= 1的类型是MutableList[Int]。人们仍然会期待编译错误,而不是函数。除了 MutableList
s(实际上所有 Seq
s)都是函数,带有 Int 参数,返回 Seq 元素的类型。该函数只是 returns 第 i 个元素。同样,这可能很方便,您可以简单地在需要函数的地方传递 seq,而不必编写 i => seq(i)
。现在你有了一个函数,它有一个 Int 参数,这是 foreach 所期望的。
不过,它不是returns单位,而是整数。但是,scala 会将其作为 Int => Unit
接受,只是丢弃该值。所以它编译。
现在来看它的作用:首先,它计算 foreach 中的参数,因此它调用 x+=1
,获取列表 x,它现在包含一个元素。然后它会调用这个函数,它是访问第 i 个元素,参数范围从 1 到 10)。这样做,它不会向列表中添加值,而只是访问给定索引处的元素。然后它立即失败,因为列表只包含一个元素,位于索引 0
,因此使用 1
调用会抛出 IndexOutOfBoundException
。