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
accon the correct side of function makes reasoning easier - lambdas in
coll.reduceLeft(_ operation _)andcoll.reduceRight(_ operation _)would have very confusing behavior ifaccwere 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.
