【问题标题】:Apply and lambdas in Scala在 Scala 中应用和 lambdas
【发布时间】:2015-12-24 08:25:35
【问题描述】:

我有以下代码

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

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

【问题讨论】:

  • 该死,我只是在写一个答案,当我意识到在这种情况下(0 until 4) foreach { builder.append("!").apply } 的行为与(0 until 4) foreach { builder.append("!").apply(_) } 不同,我无法解释

标签: scala lambda apply


【解决方案1】:

foreach 期望(在您的情况下)Int => Unit 您提供 () => StringBuilder 的函数。但是,由于StringBuilder 是一个集合,它的“应用”函数用于检索特定索引处的字符被选为在 foreach 循环中应用的函数。

您可以使用以下方法修复您的代码:

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

【讨论】:

    【解决方案2】:

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

    您的转译成 Java 的代码如下所示:

    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();
      }
    }
    

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

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

    • StringBuilder (scala.collection.mutable)
    • AbstractSeq (scala.collection.mutable)
    • AbstractSeq (scala.collection)
    • Seq (scala.collection)
    • PartialFunction (scala)
    • 函数 1 (scala)

    作为结论:

    • 您可以使用任何StringBuilder 作为从IntChar 的函数或部分函数
    • 在您的情况下,append 仅计算一次,其结果 (StringBuilder) 用作函数。

    【讨论】:

    • 非常感谢!刚从 Kotlin 切换到 Scala,Scala 中的 Kotlin 中的函数变成了只是巧合返回适当类型函数的代码块。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多