I know while using Loops, mutability comes into picture and keep things difficult to have a track of. But is it just because of mutability that recursion is considered over loops in Scala?
Additionally I understand that tail recursion doesn't add to your call stack but not all the problems can be solved using tail Recursion right? What about using an Accumulator based approach which also seems to be sufficient enough for avoiding stack overflow cases? What can be more performant between tail Recursion and Accumulator based Recursion Approach?
In short, I have two questions:
- Since tail recursion cannot be used to solve all loop problems (or can it?) isn't looping the better or the only solution for some specific use cases?
- What is the difference between tail recursion and accumulator based recursion and which is more performant based on the space complexity and call stack occupied?
Edit 1:
Example of a non tail recursive function (which uses an intermediate tail recursive function) that is converted in Accumulator based recursion (Factorial Function):
Without Accumulator:
def factorial(n: Int): Int = {
if (n <= 1) 1
else n * factorial(n - 1)
}
With Accumulator:
def tailRecFactorial(n: Int): BigInt = {
@tailrec
def factorialHelper(x: Int, accumulator: BigInt): BigInt = {
if (x <= 1) accumulator
else factorialHelper(x - 1, x * accumulator)
}
factorialHelper(n, 1)
}