The most important point in your question is the function stack. return (num * factorial(num - 1)); is not in the tail position, i.e. the recursive call of factorial(num - 1) not the last action of the recursive function. The last action is multiplying by num . Therefore, your factorial should work on the stack. When you delete a stack with a tail recursive version of factorial(acc * num, num - 1) , you need to map the stack to an additional argument, namely acc .
Loops themselves are not as expressive as recursion due to the lack of a stack. This means that you cannot implement a loop version that is equivalent to your non-recursive implementation without a tail. Actually, the while implementation is equivalent to the tail recursive version of factorial . A recursive tail means that all recursive calls share the stack frame and therefore are excluded - there is no longer a stack. Your tmp just acc - it simulates a stack of functions and accumulates the result of iterations. Try implementing factorial with a while , but without an additional variable like tmp . It's impossible.
However, the problem with irregular recursive solutions is that they can explode the stack, while tmp just stored on the heap.
Here is a complete tail recursive solution:
function fact(acc, num) { return num > 1 ? fact(acc * num, num - 1)
Output:
Are there situations where recursion is necessary or even very preferable for a while loop
No. Tail recursion and simple loops are equivalent. Recursion without a tail and a loop with its own stack are almost equivalent, except that a non-tail recursive function saves its intermediate results in a function stack and, thus, a stack overflow can occur. Loops with their own stack store it on the heap and therefore do not have this limitation.
source share