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 )
}
}
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
.