Why compiler does not translate Scala
(1,2,3,4,5,6).foldRight(10)(_ * _)
to Java equivalent
final int[] intArray = new int[]{1,2,3,4,5,6};
int accumulator = 10;
for(int i = intArray.legth - 1; i >=0; i--) {
accumulator = intArray[i] * accumulator;
}
The question is: Why foldLeft and reduceLeft are tail recursive, but their right counteparts aren't?
Here are links which says that right handed aren't tail recursive. I am asking why it is so.
How do you know when to use fold-left and when to use fold-right?
Implications of foldr vs. foldl (or foldl')
http://programming-scala.labs.oreilly.com/ch08.html
It's a question of how the folding proceeds. The foldLeft
operation arranges
Seq(1, 2, 3).foldLeft(10)(_ - _)
as
(((10 - 1) - 2) - 3)
(which is 4) while foldRight
arranges
Seq(1, 2, 3).foldRight(10)(_ - _)
as
(1 - (2 - (3 - 10)))
(which is -8).
Now, imagine you're pulling the numbers 1, 2, and 3 from a bag and making the calculation pencil-on-paper.
In the foldRight
case you're forced to do it like this:
In the foldLeft
case, you can do it like this:
but you wouldn't, because you can also do it like this:
Regardless of how many numbers there are in the bag, you only need to have one value written on paper. Tail Call Elimination (TCE) means that instead of building a large structure of recursive calls on the stack, you can pop off and replace an accumulated value as you go along. (I.e., the recursively expressed computation is essentially performed in an iterative manner.)
As others have noted, a random-access structure such as an ArrayLike
allows the foldRight
to be rearranged into a foldLeft
operation, and so become eligible for TCE. The description above does hold for cases where this is impossible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With