我有以下代码.
import scala.collection.mutable.MutableList
val x = MutableList[Int]()
(1 to 10).foreach(x+=1)
Run Code Online (Sandbox Code Playgroud)
我收到了java.lang.IndexOutOfBoundsException: 1错误.
但,
(1 to 10).foreach(println) this does not throw any error.
Run Code Online (Sandbox Code Playgroud)
在indexOutOfBoundException可以通过使用lambda操作如下解决:
(1 to 10).foreach(_ => x+=1)
Run Code Online (Sandbox Code Playgroud)
这一切都很好.
我的问题是:
1.为什么我需要在第一种情况下使用lambda运算符而不像第二种情况?
2.为什么编译器抛出IndexOutOfBoundException,我想这不是这个Exception的正确上下文.
会发生什么事情是图书馆中的一些小便利,它们会帮你咬人.
foreach签名是
def foreach(f: A => Unit): Unit
Run Code Online (Sandbox Code Playgroud)
在你的情况下,A是Int,所以它需要一个函数,它接受一个Int并返回Unit.很好println.请注意,您刚刚写过println,而不是println(something),这不是一个函数.
人们会期望x + = 1只是一个指令,因此它将具有类型Unit,而不是函数,而不是foreach的有效参数,并且会得到一个有用的编译时错误.但+=在MutableList实际返回的名单,这是方便,因为它使链式操作更加方便:
def +=(elem: A): this.type
Run Code Online (Sandbox Code Playgroud)
所以x + = 1的类型是MutableList [Int].人们仍然期望编译错误,而不是函数.除了MutableLists(所有Seqs实际上)都是函数,使用Int参数,返回Seq元素的类型.该函数只返回第i个元素.再次,这可能很方便,您可以简单地传递期望函数的seq,而不是必须写i => seq(i).现在你有了一个带有Int参数的函数,它是foreach所期望的.
不过,它不会返回Unit,而是Int.但是,scala会接受这一点Int => Unit,只是放弃了价值.所以它编译.
现在它做了什么:首先,它评估foreach中的参数,因此它调用x+=1,获取列表x,现在包含一个元素.然后它将调用此函数,该函数是对参数范围从1到10的第i个元素的访问.这样做,它不会向列表添加值,而只是访问给定索引处的元素.然后它立即失败,因为列表只包含一个元素,在索引处0,所以调用时1会抛出IndexOutOfBoundException.