Scala:reduceLeft 和 reduceRight 是否在不同位置有累加器?
Scala: Does reduceLeft and reduceRight have accumulator at different positions?
我对 Scala 中的 reduceleft 和 reduceRight 方法有点困惑。这是我正在测试的片段:
val intList = List(5, 4, 3, 2, 1);
println(intList.reduceRight((curr, acc) => { //Reduce right me y is accumulator
println(s"First Curr = $curr, Acc = $acc")
curr - acc
}));
println(intList.reduceLeft((curr, acc) => { // List(1,2,3,4,5) // Accumulator is the first Element
println(s"Second Curr = $curr, Acc = $acc")
acc - curr}))
输出如下所示:
First Curr = 2, Acc = 1
First Curr = 3, Acc = 1
First Curr = 4, Acc = 2
First Curr = 5, Acc = 2
3
Second Curr = 5, Acc = 4
Second Curr = -1, Acc = 3
Second Curr = 4, Acc = 2
Second Curr = -2, Acc = 1
在两次迭代中,我观察到的是,在 reduceRight 的情况下,我们有 (curr
,acc
) [意思是 curr 作为第一个参数传递,累加器作为第二个传递],而如果在 reduceLeft
中我们有 (acc
,curr
).
这种论点不一致背后有什么具体原因吗?
让我们使用一点可视化:
reduceLeft
:
a b c d e
acc1 = f(a, b) \/ / / /
acc2 = f(acc1, c) \/ / /
acc3 = f(acc2, d) \/ /
acc4 = f(acc3, e) \/
reduceRight
:
a b c d e
\ \ \ \/ acc1 = f(d, e)
\ \ \/ acc2 = f(c, acc1)
\ \/ acc3 = f(b, acc2)
\/ acc4 = f(a, acc3)
参数的顺序帮助我们记住参数的来源和计算顺序。因为这对于不要混淆左关联和右关联操作非常重要:
- 任何视觉帮助都很重要,在函数的正确一侧写
acc
会使推理更容易
如果 coll.reduceLeft(_ operation _)
和 coll.reduceRight(_ operation _)
中的 - lambda 表达式 非常 令人困惑的行为
acc
在这两种情况下
想象一下,如果您定义了一个右结合运算符,例如a ** b
(a 的 b 次方)。数学中的求幂是右结合的,所以 a ** b ** c
应该表现得像 a ** (b ** c)
。有人决定使用 rightReduce
来计算这种用例,因为它恰好实现了这种行为。他们
List(a, b, c).reduceRight(_ ** _)
然后他们得知有人决定 acc
应该在左侧,因为他们希望它与 reduceLeft
“一致”。 那 将与您从数学中获得的每一个直觉更加不一致。
我对 Scala 中的 reduceleft 和 reduceRight 方法有点困惑。这是我正在测试的片段:
val intList = List(5, 4, 3, 2, 1);
println(intList.reduceRight((curr, acc) => { //Reduce right me y is accumulator
println(s"First Curr = $curr, Acc = $acc")
curr - acc
}));
println(intList.reduceLeft((curr, acc) => { // List(1,2,3,4,5) // Accumulator is the first Element
println(s"Second Curr = $curr, Acc = $acc")
acc - curr}))
输出如下所示:
First Curr = 2, Acc = 1
First Curr = 3, Acc = 1
First Curr = 4, Acc = 2
First Curr = 5, Acc = 2
3
Second Curr = 5, Acc = 4
Second Curr = -1, Acc = 3
Second Curr = 4, Acc = 2
Second Curr = -2, Acc = 1
在两次迭代中,我观察到的是,在 reduceRight 的情况下,我们有 (curr
,acc
) [意思是 curr 作为第一个参数传递,累加器作为第二个传递],而如果在 reduceLeft
中我们有 (acc
,curr
).
这种论点不一致背后有什么具体原因吗?
让我们使用一点可视化:
reduceLeft
:
a b c d e
acc1 = f(a, b) \/ / / /
acc2 = f(acc1, c) \/ / /
acc3 = f(acc2, d) \/ /
acc4 = f(acc3, e) \/
reduceRight
:
a b c d e
\ \ \ \/ acc1 = f(d, e)
\ \ \/ acc2 = f(c, acc1)
\ \/ acc3 = f(b, acc2)
\/ acc4 = f(a, acc3)
参数的顺序帮助我们记住参数的来源和计算顺序。因为这对于不要混淆左关联和右关联操作非常重要:
- 任何视觉帮助都很重要,在函数的正确一侧写
acc
会使推理更容易
如果 - lambda 表达式 非常 令人困惑的行为
acc
在这两种情况下
coll.reduceLeft(_ operation _)
和 coll.reduceRight(_ operation _)
中的 想象一下,如果您定义了一个右结合运算符,例如a ** b
(a 的 b 次方)。数学中的求幂是右结合的,所以 a ** b ** c
应该表现得像 a ** (b ** c)
。有人决定使用 rightReduce
来计算这种用例,因为它恰好实现了这种行为。他们
List(a, b, c).reduceRight(_ ** _)
然后他们得知有人决定 acc
应该在左侧,因为他们希望它与 reduceLeft
“一致”。 那 将与您从数学中获得的每一个直觉更加不一致。