scala中foldright和foldleft的参数顺序

scala中foldright和foldleft的参数顺序,scala,Scala,为什么foldLeft需要 f: (B, A) => B 和foldRight take f: (A, B) => B foldLeft本可以编写为接受f:(A,B)=>B. 我试图理解参数顺序差异的原因。它应该向您显示聚合的方向。FoldLeft从左到右聚集,因此您可以想象收集器B在靠近每个A时在左侧聚集东西: 如果您有以下情况: Vector(1,2,3,4,5).foldLeft(0)((b,a) => b + a) Vector(1,2,3,4,5).foldRi

为什么
foldLeft
需要

f: (B, A) => B
和foldRight take

f: (A, B) => B
foldLeft
本可以编写为接受
f:(A,B)=>B.

我试图理解参数顺序差异的原因。

它应该向您显示聚合的方向。FoldLeft从左到右聚集,因此您可以想象收集器B在靠近每个A时在左侧聚集东西:

如果您有以下情况:

Vector(1,2,3,4,5).foldLeft(0)((b,a) => b + a)
Vector(1,2,3,4,5).foldRight(0)((a,b) => a + b)
然后你就会有这种行为

 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)
  ...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)
另一方面,FoldRight从右侧聚合内容。因此,如果您有类似以下内容:

Vector(1,2,3,4,5).foldLeft(0)((b,a) => b + a)
Vector(1,2,3,4,5).foldRight(0)((a,b) => a + b)
然后你就会有这种行为

 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)
  ...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)

@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

简而言之,这个属性称为“交换性”,因此对于非交换的
pow
foldLeft
foldRight
是不同的。同时,在并行收集上调用的
reduce(verbosePower)
也不会给出稳定的结果。@dk14对正在发生的事情进行了很好的数学总结。