首页 > 解决方案 > 为什么此代码编译并在执行时给出运行时错误

问题描述

此 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 += cStringBuilder

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

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

标签: scalastringbuilder

解决方案


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

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

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

因此,当您考虑 external 的第一次迭代时foreach,您拥有c = 'h'并遵循,

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

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

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

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

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


推荐阅读