Reputation: 4659
I have the following piece of code
scala> val builder = new StringBuilder("foo bar baz ")
builder: StringBuilder = foo bar baz
scala> (0 until 5) foreach { builder.append("!") }
scala> builder.toString
res15: String = foo bar baz !
I guess that in reality something like
(0 until 5) foreach builder.append("!").apply
happens. Can anyone explain to me why that happens or if I'm wrong what really happens?
Upvotes: 3
Views: 207
Reputation: 10882
To understand what's happening I used my small tool scala-to-java.
Your code transpiled to Java looks like this:
public final class _$$anon$1 {
private final StringBuilder builder = new StringBuilder("foo bar baz ");
private StringBuilder builder() {
return this.builder;
}
{
RichInt$.MODULE$.until$extension0(Predef$.MODULE$.intWrapper(0), 5).foreach((Function1<Object, Object>)this.builder().append("!"));
this.builder().toString();
}
}
As you can see, result of the builder.append("!")
, which is also StringBuilder
is simply cast to Function1
and used as a function argument in foreach.
Apparently, StringBuilder
is indeed a function, if you check it's type hierarchy:
As a conclusion:
StringBuilder
as an function or partial function from Int
to Char
append
is evaluated only once and it's result (StringBuilder
) is used as a function.Upvotes: 7
Reputation: 7152
foreach
expects a function from (in your case) Int => Unit
you provide () => StringBuilder
. However, as StringBuilder
is a collection, it's 'apply' function to retrieve a the Character at a specific index is selected as the function to apply in the foreach loop.
You can fix your code with:
(0 until 5) foreach { _ => builder.append("!")}
Upvotes: 2