为什么此代码会编译并在执行时出现运行时错误

Xol*_*lve 3 stringbuilder scala

此 Scala 代码在 Scala 2.13 下编译

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

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

以下代码运行良好,没有例外。唯一的变化是添加_foreach参数函数的占位符:

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

Sar*_*ngh 5

你的问题的答案在于String.apply()StringBuilder.apply()更确切地说。

你看,foreach期待一个功能。更确切地说,是一个计算结果为函数的表达式。

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

所以当你考虑外层的第一次迭代时foreach,你有c = 'h'并遵循,

(0 until 10).foreach(res += c )
Run Code Online (Sandbox Code Playgroud)

在这里,res += cres在附加h到它之后返回。

所以......被评估的函数是resor res.applywith res = "h"。因此,上面实际上是,

(0 until 10).foreach("h".apply)
Run Code Online (Sandbox Code Playgroud)

所以,res.apply(0)一切顺利……但res.apply(1)失败了StringIndexOutOfBoundsException