问题
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?
回答1:
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:
- StringBuilder (scala.collection.mutable)
- AbstractSeq (scala.collection.mutable)
- AbstractSeq (scala.collection)
- Seq (scala.collection)
- PartialFunction (scala)
- Function1 (scala)
As a conclusion:
- You can use any
StringBuilderas an function or partial function fromInttoChar - In your case,
appendis evaluated only once and it's result (StringBuilder) is used as a function.
回答2:
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("!")}
来源:https://stackoverflow.com/questions/32800221/apply-and-lambdas-in-scala