为什么这段代码编译并在执行时给出运行时错误

Why this code compiles and it gives runtime error when it executes

此 Scala 代码在 Scala 2.13 下编译

val res = new scala.collection.mutable.StringBuilder
"hello".foreach { c =>
  if (true) {
    (0 until 10).foreach( res += c )
  }
}

如果您看到 foreach 方法缺少匿名函数的参数。当它被执行时,它为 res += c 给出了一个异常 StringIndexOutOfBoundsException 这令人费解,因为 StringBuilder 应该总是可追加的。

以下代码运行良好,没有异常。唯一的变化是添加 _ 作为 foreach 参数函数的占位符:

val res = new scala.collection.mutable.StringBuilder()
"hello".foreach { c =>
  if (true) {
    (0 until 10).foreach( _ => res += c )
  }
}

请看

的签名
def foreach[U](f: A => U): Unit = {
}

(f: A => U)  this is a function, not an expression.

您的问题的答案在于 String.apply()StringBuilder.apply() 更准确。

你看,foreach 需要一个函数。更准确地说,一个计算结果为函数的表达式。

因此,它将首先计算表达式以获得函数,然后它将应用该函数 0 until 10

因此,当您考虑外部 foreach 的第一次迭代时,您有 c = 'h' 和后续

(0 until 10).foreach(res += c )

在这里,res += c 将 return 添加 hres

所以...评估的函数是 resres.applyres = "h"。因此,以上实际上是,

(0 until 10).foreach("h".apply)

所以,res.apply(0) 进展顺利...但是 res.apply(1) 失败 StringIndexOutOfBoundsException