0

I have looked at this long and hard. I understand recursion, I understand the call stack and the concept of “Last in, first out” but in this example.

function countup(n) {
  if (n < 1) {
    return [];
  } else {
    const countArray = countup(n - 1);
    countArray.push(n);
    return countArray;
  }
}
console.log(countup(5)); // [ 1, 2, 3, 4, 5 ]

When we meet the 'base condition' and we return []; , how is the array accessible if it does not have a name? and when is the name countArray attributed to this array?

I just don’t get it!

4
  • 1
    I’m not sure what you’re asking—the array is accessible because it’s right there. I’d recommend “running” the code via pencil and paper, or less preferably, step through it in the debugger. Commented Jun 4, 2020 at 23:27
  • Accessible where? Commented Jun 4, 2020 at 23:27
  • Recursion recurses down until n===1. Then, when countup(0) is called (as countup(1-1) , an empty array is returned. In that instant, on the same line, the empty array is assigned to the variable countArray. from there 1 is pushed, and the array [1] is returned, assigned to the countArray 1 level back up the tree, and you continue recursing back up to your starting number. Commented Jun 4, 2020 at 23:36
  • Be sure to upvote any answers you found helpful, and click the checkmark on the answer you found most helpful to select it as your "chosen" answer. Commented Jun 6, 2020 at 1:21

6 Answers 6

2

It's a return value, so the value is passed back to the caller. For example, on this line:

const countArray = countup(n - 1)

...if n was 1, then 0 is passed to countup, and [] is returned. This means countArray now has the value []. Note that this is not related to recursion at all; it's the way any function call works.

Sign up to request clarification or add additional context in comments.

1 Comment

Your example clarifies it perfectly. Thanks!
2

Recursion recurses down until n===1. Then, when countup(0) is called (as countup(1-1) , an empty array is returned. In that instant, on the same line, the empty array is assigned to the variable countArray. from there 1 is pushed, and the array [1] is returned, assigned to the countArray 1 level back up the tree, and you continue recursing back up to your starting number.

This is the line where the array assignment occurs:

const countArray = countup(n - 1);

The function is called, and the return result of the function is assigned to the variable. At first it simply recurses to a deeper level. Then, when n==1, it stops recursing, gets assigned an actual value, and begins climbing back up.
It needs this definitive, base value, [] before it can climb out of its deepest level of recursion.

1 Comment

Thanks! it is much much clearer! It basically digs for a return (since it is recursive) and comes back up however levels there were and at level 'Base' an empty array is assigned and returned then n's of each level are pushed in that array
0

The array returned by return [] is the return value of the function countup.

When you do console.log(countup(5)) really you are doing:

let something = countup(5);
console.log(something);

The array returned from the function countup is being assigned to a variable, which is then written out to the console by being passed to console.log.

Comments

0

I'm not sure the best way to express this, but a step-by-step walkthrough of how code executes may help. Indentation here indicates a level of recursion (and thus a fresh "scope" for defining variables):

// n = 5
const countArray = countup(n - 1);
  // n = 4
  const countArray = countup(n - 1);
    // n = 3
    const countArray = countup(n - 1);
      // n = 2
      const countArray = countup(n - 1);
        // n = 1
        const countArray = countup(n - 1);
          // n = 0
          // n meets the condition (n < 1), so we return []
        // we got [], as the reutn value and assigned it to countArray
        // countArray = [] a this point
        countArray.push(n);
        // now countArray = [1]
        // return [1]
      // we got [1], as the reutn value and assigned it to countArray
      // countArray = [1] a this point
      countArray.push(n);
      // now countArray = [1, 2]
      // return [1, 2]
    // we got [1, 2], as the reutn value and assigned it to countArray
    // countArray = [1, 2] a this point
    countArray.push(n);
    // now countArray = [1, 2, 3]
    // return [1, 2, 3]
  // we got [1, 2, 3], as the reutn value and assigned it to countArray
  // countArray = [1, 2, 3] a this point
  countArray.push(n);
  // now countArray = [1, 2, 3, 4]
  // return [1, 2, 3, 4]
// we got [1, 2, 3, 4], as the reutn value and assigned it to countArray
// countArray = [1, 2, 3, 4] a this point
countArray.push(n);
// now countArray = [1, 2, 3, 4, 5]
// return [1, 2, 3, 4, 5]

// This value is then console logged

1 Comment

Cheerio for the effort, you've painted a picture and it's much clearer now!
0

let's see two ways to declare an empty array

const a = [];
const b = new Array();
console.log(a) // []
console.log(b) // []

So you get the same output, now with your question, [] is a way to declare an array, and javascript knows it.

Then if you have the function:

function countup(n) {
if (n < 1) {
  // return [];
  return new Array();
} else {
    const countArray = countup(n - 1);
    countArray.push(n);
    return countArray;
  }
}
console.log(countup(5)); // [ 1, 2, 3, 4, 5 ]

Maybe this way you can figure it out what is happening, you are creating and returning a new empty array, to end the clarification, let's change the function call:

// console.log(countup(5)); // [ 1, 2, 3, 4, 5 ]
const newArrayUpToFive = countup(5);
console.log(newArrayUpToFive); // [ 1, 2, 3, 4, 5 ]

// Now the empty array

const newArrayEmpty = countup(0) // the return value is new Array()
// const newArrayEmpty = new Array(); // It is like this sentence

console.log(newArrayEmpty) // []

Step by step:

console.log(countup(2));

// The function does (as n = 2)
const countArray = countup(1) // 2 - 1, Let's say this is the 'A' call
// The function has to wait for the countup return statement

// Now countup is called again with n = 1, and we have
const countArray = countup(0) // 1 - 1, 'B' call
// Again, the function has to wait for the countup return statement

// Finally countup is called n = 0 and the if condition
// is true, so:
   return [];

// B call gets the value [], in 'B' call the value of n was 1
const countArray = [];
countArray.push[1]
return countArray; // returns [1]

// A call gets the value [1], in 'A' call the value of n was 2
const countArray = [1];
countArray.push(2);
return countArray; // returns [1, 2]

So at the end, console.log is called with the value [1, 2].

2 Comments

Thanks a lot! I read all the answers and I got it. I'll rework everything on pen and paper to understand well. Basically, the 'program' went 5 levels down looking for a return and when it found it, ran the push instruction as it was climbing up every level to the top
Exactly! ,so you put every call using recursion in "wait" mode, great to know that you grasp the idea.
0

Recursion is a functional heritage and so using it with functional style yields a greater comprehension. In functional programming, you can simply replace a function call with it's return value and always get the correct answer. This is not always true for imperative programs which rely on side-effects to compute the result.

I think it helps to see the program and the spawned process like this -

const countup = (n = 0) =>
  n < 1
    ? []
    : [ ...countup(n - 1), n ]
    
console.log(countup(4))
// [ ...countup(3), 4 ]
// [ ...[ ...countup(2), 3 ], 4 ]
// [ ...[ ...[ ...countup(1), 2 ], 3 ], 4 ]
// [ ...[ ...[ ...[ ...[], 1 ], 2 ], 3 ], 4 ]
// [ ...[ ...[ ...[ 1 ], 2 ], 3 ], 4 ]
// [ ...[ ...[ 1, 2 ], 3 ], 4 ]
// [ ...[ 1, 2, 3 ], 4 ]
// [ 1, 2, 3, 4 ]

I'm not saying it's a better program (or worse!) but I do think it's easier to see how the recursive program directly relates to the recursive computational process.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.