【问题标题】:Fold function scala's immutable list折叠函数scala的不可变列表
【发布时间】:2020-04-12 22:44:18
【问题描述】:

我创建了一个不可变列表并尝试将其折叠到一个映射中,其中每个元素都映射到一个常量字符串“abc”。我这样做是为了练习。 当我这样做时,我遇到了一个错误。我不确定为什么地图(这里是具有可变地图类型的 e1)被转换为 Any。

val l = collection.immutable.List(1,2,3,4)
l.fold (collection.mutable.Map[Int,String]()) ( (e1,e2) => e1 += (e2,"abc") )

l.fold (collection.mutable.Map[Int,String]()) ( (e1,e2) => e1 += (e2,"abc") )
<console>:13: error: value += is not a member of Any
  Expression does not convert to assignment because receiver is not assignable.
       l.fold (collection.mutable.Map[Int,String]()) ( (e1,e2) => e1 += (e2,"abc") )

【问题讨论】:

    标签: scala functional-programming


    【解决方案1】:

    这里至少有三个不同的问题来源:

    1. Map[...] 不是Int 的超类型,所以你可能想要foldLeft,而不是foldfold 的行为更像"banana brackets",它希望第一个参数的行为类似于某种“零”,以及作为某种“加法”的二元运算——这不适用于可变映射和整数)。
    2. 对于foldfoldLeft,二元运算必须返回something。在这种情况下,您可能希望返回修改后的地图。这就是您需要; m 的原因(最后一个表达式是从闭包返回的内容)。
    3. m += (k, v) 不是您想的那样。它尝试使用 两个 单独的参数调用方法+=。你需要的是用一对来调用它。请改用m += ((k, v))(是的,arity 的那些问题很烦人)。

    把它们放在一起:

    l.foldLeft(collection.mutable.Map[Int, String]()){ (m, e) => m += ((e, "abc")); m }
    

    但是由于您仍然使用可变映射:

    val l = (1 to 4).toList
    val m = collection.mutable.Map[Int, String]()
    for (e <- l) m(e) = "abc"
    

    老实说,这在我看来可以说更清楚了。在foldLeft 中,我不希望地图发生变异。

    【讨论】:

      【解决方案2】:

      折叠就是将一系列输入元素组合成单个输出元素。 Scala 中的输出和输入元素应该具有相同的类型。这里是fold的定义:

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

      在您的情况下,类型 A1Int,但输出元素(总和类型)是 mutable.Map。因此,如果您想通过迭代构建Map,那么您可以使用foldLeft 或任何其他可以使用不同输入和输出类型的替代方案。这里是foldLeft的定义:

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

      解决方案:

      val l = collection.immutable.List(1, 2, 3, 4)
      l.foldLeft(collection.immutable.Map.empty[Int, String]) { (e1, e2) =>
        e1 + (e2 -> "abc")
      }
      

      注意:我没有使用 mutabe Map

      【讨论】:

      • 感谢您让我意识到 fold fold 需要列表的相同类型(或子类型)元素。那是我犯的错误。我想知道为什么 fold 和 foldLeft 的输入不同。
      猜你喜欢
      • 2015-09-23
      • 1970-01-01
      • 2018-12-24
      • 1970-01-01
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多