Recursion
https://www.freecodecamp.org/news/how-recursion-works-explained-with-flowcharts-and-a-video-de61f40cb7f9/
https://betterprogramming.pub/when-to-loop-when-to-recurse-b786ad8977de#:~:text=When%20should%20I%20use%20recursion,searching%20through%20a%20file%20system.
To avoid mutating stating, using recursion is method of doing so
functional programming, and languages leads you to use this way of coding instead of using loops
Some languages have been built to perform well with recursion
To use, must have some idea beforehand how deep the recursion will go, lest you blow the stack.
How it works
A program that jumps to a subroutine pushes the return address on the stack, to be popped when the subroutine completes. If that subroutine calls another subroutine, then it pushes its own return address on top. The stack holds all the return addresses in the correct order so that the program is always able to return control back to where it came from
Obviously, the greater the depth of nesting in your subroutines, the more stack space is required
All recursion can be transformed to loops
But some problems are easier to solve, less complex using recursion
When to use
Recursion is made for solving problems that can be broken down into smaller, repetitive problems. It is especially good for working on things that have many possible branches and are too complex for an iterative approach.
https://stackoverflow.com/questions/3021/what-is-recursion-and-when-should-i-use-it
Avoiding blowing stack
The key is to position the subroutine calls so that they are in tail position
This means that there are no more instructions between the return of control from the subroutine, and the end of the routine that called it.
ie when subroutine A calls subroutine B from tail position, control returns from B only to return immediately to the caller of A
Example of not using tail poistion is factorial impl
The recursive call to factorial is not in tail position, because its result must be multiplied with n to calculate the return value for the outer function call
why does this work
a subroutine call in tail position can be replaced with a goto. Unlike a subroutine call, a goto does not anticipate control returning to the calling routine, so no return address is pushed on the call stack.
Example
a -> b -> c
if the call to C is in tail position then B may as well go to C directly, leaving its own return address on top of the call stack, because C will pop that address and return directly to A. This is what we wanted to happen anyway. This is called tail call elimination and the benefit is twofold: firstly, we’ve avoided one unnecessary jump instruction, and much more importantly, we’ve avoided growing the call stack.
If you eliminate tail calls this way in a recursive algorithm, you get a routine that repeatedly jumps to its entry point until the terminating condition is achieved. In machine terms this is no different to a regular loop!
But this is programming language specific opitmisation
Disadvantages of recursion
Issues with stackoverflow errors
Java has no Tail Call optimization (yet), hence yes, recursive solutions may give you StackOverflowError.
performance loss as it has to create new stack frame and do some other stuff for each recursive invocation.
Readability might be harder
Harder to debug
using recursion can also restrict you from using concurrency to speed up parallel operations.
Not as performant as loops
https://stackoverflow.com/questions/41469031/is-recursion-a-bad-practice-in-general
Last updated