【问题标题】:Folding on sequence of blocks按块顺序折叠
【发布时间】:2014-11-07 19:38:12
【问题描述】:

我想在我的 Scala 代码中实现动作链。我想我可以为此使用“折叠”。所以,假设我有这样声明的动作序列:

val chainOfActions: Seq[String => String] = Seq(
  {resultFromPreviousAction => 
    println("Inside the first action")
    "Result from the first action"
  },
  {resultFromPreviousAction => 
    println("Inside the second action")
    resultFromPreviousAction + " > " + "Result from the second action"
  }
)

上面的代码可以编译(我在 scala 控制台中尝试过)。

接下来是应用折叠:

chainOfActions.fold("") { (intermediateText, action) =>
  action(intermediateText)
}

但上面的代码给出了以下错误:

<console>:10: error: Object does not take parameters
                action(intermediateText)

嗯...为什么我的动作失去了它的类型(我期望类型是“String => String”)?

所以我尝试声明类型:

type MyBlockType = String => String

并以这种方式声明我的 Seq:

val chainOfActions: Seq[MyBlockType] = Seq(
  {resultFromPreviousAction => 
    println("Inside the first action")
    "Result from the first action"
  },
  {resultFromPreviousAction => 
    println("Inside the second action")
    resultFromPreviousAction + " > " + "Result from the second action"
  }
)

仍然出现同样的错误。所以,我试图检查“动作”的实际类型......:

chainOfActions.fold("") { (intermediateText, action) =>
  println(action.getClass)
  "Test it"
}

我在控制台中得到了这个信息:

class $line101.$read$$iw$$iw$$anonfun$1
class $line101.$read$$iw$$iw$$anonfun$2
res58: Object = Test it

所以...,它是正确的(它是一个函数)。但是为什么 Scala 不将其识别为对象呢?

请帮我指出我哪里做错了。

谢谢, 拉卡

【问题讨论】:

    标签: scala functional-programming fold method-chaining


    【解决方案1】:

    在这种情况下你需要'foldLeft':

    val result = chainOfActions.foldLeft("") {
      case (intermediateText, action) => action(intermediateText)
    }
    

    使用 fold,您需要为初始值和 Seq 中的每个值具有相同的类型。但是您的初始(和输出)值是 String,但集合是 String => String

    方法签名:

     def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1
     def foldLeft[B](z: B)(op: (B, A) => B): B
    

    所以如果你想使用折叠,你的初始值需要是 String => String,例如带有标识的它将是:

    val result = chainOfActions.fold(identity[String] _)((l, r) => l andThen r).apply("")
    

    【讨论】:

    • 谢谢,它有效!您提到的类型差异导致 scala 向下转换为 Object。否则(如果我的初始值为 String => String),我想我可以放弃模式匹配,对吧?
    • @user3443096 是的,应该在没有模式匹配的情况下工作。试试这个val result = chainOfActions.foldLeft("")(_ _)
    • @Eugene :它有效(具有身份的那个)。让我掌握魔法:)... at_Sergey:你给我的那条线没有用。它给出: :9: error: missing parameter type for extended function ((x$1) => chainOfActions.foldLeft("")((x$1: (() => )))) val 结果= chainOfActions.foldLeft("")(_ _)
    • 顺便说一句....我刚刚了解到可以在一行代码中实现:D:Function.chain(chainOfActions)("")
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 2014-07-04
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    • 2018-03-18
    • 2018-02-13
    相关资源
    最近更新 更多