在 Scala 中应用和 lambda

Apply and lambdas in Scala

我有如下一段代码

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 !

我猜现实中是这样的

(0 until 5) foreach builder.append("!").apply

发生了。谁能向我解释为什么会这样,或者如果我错了到底发生了什么?

foreach 需要一个函数(在您的情况下)Int => Unit 您提供 () => StringBuilder。但是,由于 StringBuilder 是一个集合,因此选择 'apply' 函数来检索特定索引处的字符作为要在 foreach 循环中应用的函数。

您可以通过以下方式修复您的代码:

(0 until 5) foreach { _ => builder.append("!")}

为了了解发生了什么,我使用了我的小工具 scala-to-java

您的代码转换为 Java 如下所示:

public final class _$$anon {
  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();
  }
}

如您所见,builder.append("!") 的结果也是 StringBuilder,只是简单地转换为 Function1 并用作 foreach 中的函数参数。

显然,StringBuilder 确实是一个函数,如果您检查它的类型层次结构:

  • 字符串生成器 (scala.collection.mutable)
  • 抽象序列 (scala.collection.mutable)
  • 抽象序列 (scala.collection)
  • 顺序 (scala.collection)
  • 偏函数 (scala)
  • 函数 1 (scala)

作为结论:

  • 您可以使用任何 StringBuilder 作为函数或从 IntChar
  • 的部分函数
  • 在你的例子中,append 只计算一次,它的结果 (StringBuilder) 被用作一个函数。