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

时间:2020-01-15 17:08:24

标签: scala stringbuilder

此Scala代码在Scala 2.13下编译

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

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

以下代码运行正常,没有例外。唯一的变化是将_添加为foreach参数函数的占位符:

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

2 个答案:

答案 0 :(得分:5)

更确切地说,您的问题的答案位于String.apply()StringBuilder.apply()中。

您看到,foreach需要一个功能。用更准确的话来说就是一个计算为函数的表达式。

因此,它将首先对表达式求值以获取函数,然后将其应用于0 until 10

因此,当您考虑外部foreach的第一次迭代时,您有c = 'h'及其后继者,

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

在这里,res += cres附加到其后将返回h

所以...求值函数是resres.applyres = "h"。因此,以上实际上是

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

因此,res.apply(0)进行得很好...但是res.apply(1)失败,出现StringIndexOutOfBoundsException

答案 1 :(得分:-3)

请参阅

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

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

相关问题