I am a littlebit confused between the methods reduceleft and reduceRight in Scala. Here's a Snippet that I am testing:
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}))
And the Output is as shown below:
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
In both the iterations what I observe is that in case of reduceRight we have (curr
,acc
) [Meaning curr is passed as first argument and accumulator as second], whereas in case of reduceLeft
we have (acc
,curr
).
Is there any specific reason behind this inconsistency in the arguments?
CodePudding user response:
Let's use a little visualization:
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)
The order of arguments help us remember the where the arguments came from and in which order they were evaluated. Because this is quite important to not confuse left-associative and right-associative operations:
- any visual help matters and writing
acc
on the correct side of function makes reasoning easier - lambdas in
coll.reduceLeft(_ operation _)
andcoll.reduceRight(_ operation _)
would have very confusing behavior ifacc
were on left in both cases
Imagine if you defined a right-associative operator e.g. a ** b
(a to the power of b). Exponentiation in math is right-associative, so a ** b ** c
should behave like a ** (b ** c)
. Someone decides to calculate such use case using rightReduce
, because it implements exactly this behavior. They do
List(a, b, c).reduceRight(_ ** _)
and then they learn that someone decided that acc
should be on left side because they wanted it to be "consistent" with reduceLeft
. That would be much more inconsistent with every intuitions that you carried from mathematics.