Are you tired of the convenience that loops provide? Then do we have the solution for you!
Much like a for or while loop, recursive functions will continue to execute until it is stopped via code.
The recursive function accomplishes this feat by calling its own function within the function itself. Sound confusing? Well let's break it down.
Recursion has two important parts to keep it working. The base case and recursion case.
What is a Recursion case?
A recursion case is a function that will invoke itself unless it is stopped by the base case. If there is no base case to stop it, the recursive case will call itself forever. Take a look at this example:
function infinite(){
console.log('Invoked');
infinite();
}
infinite();
In the above example we can see that we are invoking the infinite function that will console.log 'Invoked' and then call itself again. This will happen because there is no Base Case to stop it.
What is a Base Case?
A base case is usually a boolean that will execute when the argument meets the specific criteria of the boolean. In a for loop, this can either be ending point of the loop statement or a return statement within. In a recursive function, a Base Case is declared before the recursive case so the argument is tested before it gets sent to the recursive case. If a base case wasn't in the recursive function, the function would loop over itself an infinite number of times!
Let's see an example:
function countDown(num){
//base case (this is what will eventually end the recursion)
if (num === 0) {
return;
}
//recursion case (if the base case was not triggered,
// the recursion case executes)
console.log(num); // we print the current argument for the countdown
countDown(num - 1); // here we call the function inside itself
//passing the argument -1. This repeats
//the process until base case executes.
}
countDown(5);
In this example, we invoke our recursive function with the argument of 5. It first goest to the base case to check if the argument(5) strictly equals 0. It does not, so the program proceeds to the next line which logs the argument. After the log, we come to the recursive case. Here we call the function with the argument being decremented.
// logs 5, calls countDown with (5 - 1 === (4))
//logs 4, calls countDown with (4 - 1 === (3))
//logs 3, calls countDown with (3 - 1 === (2))
//logs 2, calls countDown with (2 - 1 === (1))
//logs 1, calls countDown with (1 - 1 === (0))
When we execute the function again, the Base Case is triggered and ends the program.
Multiple Base Cases
Sometimes one Base Case is not enough. Check this out:
function isBear(str){
//base case
if (str === 'bear') {
return console.log(true);
}
//recursion case
isBear(str.slice(1));
}
isBear('grizzlybear');
isBear('koala');
In this example, the first invocation will work as intended because we will keep recursion looping over the grizzlybear string, slicing off the first letter each iteration until only bear is left of the string. When the bear string gets to the base case, it is tested and found to strictly equal 'bear' and the program concludes by returning true. However, if we were to invoke isBear by passing koala as the argument, we will loop forever. We can solve this issue by putting another base case in:
function isBear(str){
//FIRST BASE CASE
if (str === 'bear') {
return console.log(true);
}
//SECOND BASE CASE
if (str.length === 0){
return console.log(false)
}
//RECURSION CASE
isBear(str.slice(1));
}
isBear('grizzlybear');
isBear('koala');
Now when we invoke with koala as the argument, the base case will trigger when there is no more string left to slice! This will result in printing false to the console.
In conclusion, recursive functions, like for/while loops will iterate over the data until their code block is triggered. Recursion is just a little more elegant of an approach. Next time when you are writing a for loop, why not give recursion a try? If you want to dive deeper, check out these helpful blogs:
Top comments (2)
Great explanation.
Another difference between iteration and recursion is that an infinite iterative loop will likely go on forever; an 'infinite' recursive loop will most likely cause a stack-overflow error/exception.
A great use-case for recursive algorithms is traversing nodes in a data tree. However, they can be tricky to debug because the call stack often consists of similar looking frames, depending on how deep the recursion is at that point.
What an awesome explanation of recursion. Thanks so much for sharing, James!