RECURSION: A Beginner’s Guide

RMAG news

The concept of recursion in JavaScript programming has always been equal parts fascinating, intimidating, and mystifying to me. Today, I will let the fascinating part guide me as I grapple with explaining recursion to you, my reader, as well as to myself. May we both have a fuller understanding of the beauty, intricacies, and utility inherent in this humble programming technique by the end of this blog post.

What is Recursion?

Before we get to the ‘why’ and the ‘how’, it might be a good idea to start with the ‘what’. What exactly is recursion in the context of programming? According to MDN, recursion is “the act of a function calling itself.”

Take a look at this simple example:

function infiniteJest() {
console.log(HA!);
infiniteJest();
}

The function infiniteJest() calls itself within its own body, making it a recursive function. What do you think would happen if we called this function?

If you call infiniteJest(), it will print “HA!” to the console. And then it will print “HA!” again. And then again. And again. It will keep printing “HA!” to the console until the end of time, unless someone or something stops it. This is not a situation we want to find ourselves in, so how can we modify our function to prevent it from being infinitely loopy? If you said “use a base case,” then you are absolutely correct! Every recursive function needs a base case so that it knows when to stop.

One way to do this is to give infiniteJest a counter parameter so we can tell the function how many times we want it to print “HA!”:

function infiniteJest(counter) {
if (counter > 0) {
console.log(HA!);
infiniteJest(counter 1);
}
}

Why Use Recursion?

Now that we know what recursion is and the basics of how it works, you might wonder why we would choose recursion over simpler alternatives like loops. We probably don’t want to create a function like infiniteJest() that will just laugh at us all day long, and even if we did, there are simpler ways to achieve this.

One major reason that recursion is sometimes preferred over loops is that it can solve complex problems in a more elegant and readable way. Also, it often takes a lot less code. Let’s look, for example, at a recursive way of calculating factorials:

function factorial(n) {
if (n === 0) {
return 1;
}
return n * factorial(n 1);
}

We can also find factorials using a for loop, but it takes more code, is more confusing, and doesn’t look as nice. Many situations naturally lend themselves to recursive techniques, including problems that can be broken down into smaller sub-problems, but recursion is not always the best solution.

The Dangers of Recursion

If we wanted to find the factorial of a very large number, for example, using a for loop would actually be preferable. If we used recursion, we would run the risk of stack overflow, which is an error that happens when our program tries to “take up more space than it was assigned,” according to MDN. This is one of the dangers of recursion. It uses more memory than iterative approaches and is often slower.

We also run the risk of stack overflow when we neglect to provide a base case or when our base case is not met. This is why it is extremely important to always have a condition that, when met, will stop the recursion.

Conclusion

Recursion is a powerful tool in programming, offering elegant solutions to many problems by using the function’s ability to call itself. By understanding how to use it and when not to use it, we can recurse effectively while avoiding common dangers like stack overflow. Whether you choose recursion or iteration depends on the problem at hand, but mastering recursion opens doors to solving complex problems with clarity and efficiency.

Explore recursion further in your programming journey—it’s not just a technique but a mindset that expands your problem-solving capabilities.

Further Exploration

If you’re eager, as I am, to deepen your understanding of recursion, consider exploring more advanced topics such as tail recursion optimization, memoization, and practical applications in algorithms like tree traversal and dynamic programming.