Search code examples
scalastringbuilder

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


This Scala code compiles under Scala 2.13

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

If you see the foreach method is missing argument for anonymous function. When it is executed it gives an exception StringIndexOutOfBoundsException for res += c which is puzzling since StringBuilder should always be appendable.

Following code runs fine and there are no exceptions. The only change is adding _ as placeholder for foreach parameter function:

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

Solution

  • The answer to your question lies in String.apply() or StringBuilder.apply() to be more exact.

    You see, foreach expects a function. In more exact words, an expression which evaluates to a function.

    So, it will first evaluate the expression to get the function then it will apply that function for 0 until 10

    so when you consider the first iteration of outer foreach, you have c = 'h' and following,

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

    Here, res += c will return res after appending h to it.

    So... the evaluated function is res or res.apply with res = "h". Hence, the above is actually,

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

    So, res.apply(0) goes well... but res.apply(1) fails with StringIndexOutOfBoundsException.