【问题标题】:Order of parameters to foldright and foldleft in scalascala中foldright和foldleft的参数顺序
【发布时间】:2014-01-31 04:33:27
【问题描述】:

为什么foldLeft会被占用

f: (B, A) => B

和 foldRight 取

f: (A, B) => B

foldLeft 本来可以写成 f: (A, B) => B. 我试图理解参数顺序不同的原因。

【问题讨论】:

    标签: scala


    【解决方案1】:

    它应该向您显示聚合的方向。 FoldLeft 从左到右聚合,所以你可以想象累加器 B 在接近每个 A 时将左侧的东西聚在一起:

    如果你有类似的东西:

    Vector(1,2,3,4,5).foldLeft(0)((b,a) => b + a)
    

    然后你会得到这种行为

     B    ...As...
    ---------------
    (0), 1, 2, 3, 4, 5
    (0+1),  2, 3, 4, 5
    (0+1+2),   3, 4, 5
    (0+1+2+3),    4, 5
    (0+1+2+3+4),     5
    (0+1+2+3+4+5)
    

    另一方面,FoldRight 从右侧聚合事物。所以如果你有类似的东西:

    Vector(1,2,3,4,5).foldRight(0)((a,b) => a + b)
    

    然后你会得到这种行为

      ...As...     B
    -----------------
    1, 2, 3, 4, 5 (0)
    1, 2, 3, 4, (5+0)
    1, 2, 3,  (4+5+0)
    1, 2,   (3+4+5+0)
    1,    (2+3+4+5+0)
        (1+2+3+4+5+0)
    

    【讨论】:

      【解决方案2】:

      @dhg 已经提供了一个很好的答案。我的例子说明了一个有趣的微妙之处:即,有时最初的顺序 值被传递给给定的函数事项。所以我想我会在有机会的时候发布这个 对 foldRight 的行为与 foldLeft 不同的情况感兴趣 具有相同的初始值、相同的函数和相同的输入列表。

      考虑下面的幂运算:

         def verbosePower(base:Double, exp:Double) = { 
              println(s"base=$base / exp=$exp") ; 
              math.pow(base, exp) 
         }
         var X =  List(2.0,3).foldLeft(1.0) (verbosePower)
         System.out.println("x:" + X);
      
         X =  List(2.0,3).foldRight(1.0) (verbosePower)
         System.out.println("x:" + X);
      

      foldLeft 的输出和结果是:

      base=1.0 / exp=2.0
      base=1.0 / exp=3.0
      X: Double = 1.0
      

      foldRight 的输出和结果是:

      base=3.0 / exp=1.0
      base=2.0 / exp=3.0
      X: Double = 8.0
      

      【讨论】:

      • 简而言之,这个属性叫做“交换性”,所以对于不可交换的powfoldLeftfoldRight是不同的。并且reduce(verbosePower) 调用并行收集也不会给出稳定的结果。
      • @dk14 很好的数学总结。
      猜你喜欢
      • 2013-06-12
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 2017-03-25
      • 2011-09-09
      • 1970-01-01
      • 2012-03-25
      • 1970-01-01
      相关资源
      最近更新 更多