Questions about "Use Recursion to Create a Countdown"

  1. How come n is inclusive if n - 1 gets evaluated before push/unshift?
  2. How come countArray's value is an Array when initialized?
Code
function countdown(n){
  if (n < 1) {
    return [];
  } else {
    const countArray = countdown(n - 1);
    countArray.unshift(n);
    return countArray;
  }
}

Challenge: Use Recursion to Create a Countdown

Link to the challenge:

How come n is inclusive if n - 1 gets evaluated before push/unshift ?

Because that line just gets the array. It is the unshift that is adding the value, and that value is still n, whatever the n is on that call. For the first call, n is still the original value.

How come countArray 's value is an Array when initialized?

It isn’t, kind of. This is part of the magic of recursion.

So if we call it with countdown(5), it gets into the function with n is 5. That is > 1 so we hit the else. We get to the line:

const countArray = countdown(n - 1);

It tries to evaluate the right side of that expression but it is another function call. So… This function call gets suspended, saved in memory on the call stack - it can’t be competed. We have to make a new function call, essentially countdown(4). We have the same things happen - it can’t be completed, so we make a new function call, countdown(3).

This keeps happening until we get to the “base case” where n < 1 and we finally return something. This is the first function call that actually completes and returns something. All the other function calls are still on the call stack, half-completed, waiting for the returns from their function calls.

So, the last call (n = 0) is done and returns an empty array. So, it pops the last function off the call stack and resumes. It evaluated:

const countArray = countdown(0);

to be:

const countArray = [];

and then we unshift the current n (which is 1 in this function call) onto the array and return that.

That gets received by the next function popped off the call stack (where n = 2) and do the same evaluation, but now unshift a 2 onto the array and return that.

This continues down, unravelling the call stack until we reach the original call, that finally completes and gives us our answer.

Yes, this is confusing.

Yes, this is kind of a strange example. But many recursion uses get really “mind-trippy” so this is a good starting example.

Don’t be worried if this confuses you. There are jobs where you almost never use recursion - I average less than 1 per year. There are jobs where you do a lot, but that usually depends on the data structures being used.

I mean, I think it’s good to know the basics, just to know, and because they come up on job interviews. But don’t freak out if it is too confusing for now. It took me a long while to understand them.

I might suggest checking out some videos - I think this is something that could be explained much easier (at least on a conceptual level) graphically, showing how the function calls are building up in the call stack and the data they return.

2 Likes