After you call countup(n - 1)
, the lines below are executed yes, but only after this call returns.
To make it simple, let’s see what happens when you call countup(2)
:
countup(2)
: n
is equal to 2, so does not enter the if (n < 1)
- is called
countup(n - 1)
, that is to say, countup(1)
- within the call
countup(1)
: n
is equal to 1, so does not enter the if (n < 1)
- is called
countup(n - 1)
, that is to say, countup(0)
- within the call
countup(0)
: n
is equal to 0, then enters the if (n < 1)
and returns an empty array ([]
)
countup(0)
returned the empty array, which was placed in the variable countArray
(is what the line const countArray = countup(n - 1)
ago)
countArray.push(n)
: here n
value 1, then 1 is placed in the array (which is now [ 1 ]
)
- the array
[ 1 ]
is returned
countup(1)
returned the array [ 1 ]
, which is placed on the variable countArray
countArray.push(n)
: here n
vale 2, then 2 is placed in the array (which becomes [ 1, 2 ]
)
- the array
[ 1, 2 ]
is returned
That is, the first call starts at the initial value of n
(in the above example was 2
), and with each recursive call it decreases, until it reaches zero. When it reaches zero, it returns the empty array and the process starts to "return", inserting the numbers into the array and returning it to the previous call.
What can confuse is that with each call the context changes: the value of n
and the array countArray
being manipulated have different values. But in the end everything "joins" and the result is an array containing all the numbers from 1 to n
.
The important thing is that making a recursive call doesn’t stop the execution, as you imagine. What happens is that a recursive call may end up making other recursive calls (such as when countup(2)
calling for countup(1)
, which in turn called countup(0)
), and these calls are "hung" waiting for the others to return. And after they return, the execution continues on the following lines.
What ensures that this process does not last forever is the stopping condition (if (n < 1)
), because that’s when no more recursive calls are made.
To understand recursion, first you need to understand recursion
It might help if you think about setting the solution recursively: how I create an array containing the numbers from 1 to N
?
- if
N
< 1, the interval from 1 to N
will have no number, so the array is empty (is what the if
ago)
- if
N
>= 1 (i.e., the block else
):
- 2.a) create an array containing the numbers from 1 to
N - 1
(using this same algorithm recursively, i.e., I return to step 1, but using the value of N - 1
)
- 2.b) adding the
N
in that array
Step 2.a corresponds to const countArray = countup(n - 1)
(I solve the same problem recursively for N - 1
), and step 2.b corresponds to countArray.push(n)
.
The idea of recursion is basically this: there is a "base" case with a trivial solution (the empty array), and for the other cases you solve smaller instances of the problem recursively, until you get to the base case, and in the end you put it all together.
Explaining in another way
Because of this doubt in the comments, I will try to explain in a little more detail. To simplify, let’s assume that I called countup(1)
.
The call is made to countup(1)
:
- here the
n
is worth 1, so do not enter the if (n < 1)
- inside the block
else
:
const countArray = countup(n - 1);
← as n
worth 1, then the call is made to countup(0)
Here we pause to explain that the call to countup(0)
is "independent" of the call to countup(1)
. Although it is the same function, and it is called within itself, it is two different calls and each one executes according to its context (in this case, the value that is passed as parameter is different).
So the call countup(1)
is running the line const countArray = countup(n - 1);
. That means she needs to get back to countup(0)
and assign the value returned in the variable countArray
. I mean, she needs to wait countup(0)
fully execute.
And how countup(0)
executes? Like this:
n
is worth 0, so get in the if (n < 1)
and returns an empty array ([]
)
Like countup(0)
has already finished (returning an empty array), so countup(1)
can continue running from where you left off:
const countArray = countup(n - 1);
On this line she picks up the return of countup(0)
(the empty array) and assigns this value to the variable countArray
. Then she runs the following lines:
countArray.push(n);
return countArray;
I mean, she adds n
to the array (and how we are inside the call countup(1)
, the n
is worth 1, so number 1 will be added to countArray
).
And finally, countArray
(which is now the array [1]
) is returned, and countup(1)
ends its execution.
Note that every call to countup
is "independent": only because one is in the if
, doesn’t mean another can’t be in else
(because each one has a different context, since the values of n
that each receives is different). And just because one of them returned, it doesn’t mean that the others should return immediately: each returns only when it arrives in some line containing return
.
Similarly, when we call countup(2)
:
- here the
n
Worth 2, so don’t enter the if (n < 1)
- inside the block
else
:
const countArray = countup(n - 1);
← as n
worth 2, then the call is made to countup(1)
That is, the call countup(2)
need to wait countup(1)
end to assign the return to the variable countArray
.
And from the above explanation, we already know that countup(1)
returns the array [1]
. That is, after that countup(1)
ends, the array [1]
is returned and assigned in the variable countArray
.
After that, the call countup(2)
can continue running. The next line is countArray.push(n);
, and how countArray
is [1]
and the n
vale 2, the number 2 is added in the array, which becomes [1, 2]
.
After that the array is returned, and the result is [1, 2]
.
'within the countup(0): n is equal to 0, so enter if (n < 1) and return an empty array ([])' If it returns an empty array, wouldn’t it be right to QUIT the function? Why is ELSE executed if it is only made to be executed if the IF is false? What I mean is: if the IF is true, then the ELSE is not executed. Oh I am in doubt too. And to be quite honest and I apologize because your answer is extremely complete, from this topic I put I really did not understand
– Bruno Valle
@Brunovalle No, he only quits his job if he has one
return countup(0)
. But how you keep the return in a variable (countArray = countup(0)
), the return is stored in the variable and the execution continues. I don’t know if it helps, but imagine instead ofcountup
you called some other function (countArray = outrafuncao(n - 1)
), the functioncountup
Would you return or continue on the next line? The fact of calling the same function is only a detail, because it will be called again and each call is "independent". I don’t know if it’s further confused or helped...– hkotsubo
That is to say,
countup(0)
returns the empty array and this call ends. Butcountup(0)
was called within the execution ofcountup(1)
(and this has not yet ended, as it is within Isis and needs to continue in the following lines)– hkotsubo
@Brunovalle countup(1) enters Else and calls countup(0). And countup(0) enters if and returns the empty array. The countup(0) execution has ended, but countup(1) has not yet, as it still needs to execute the rest (assigns the countup(0) return in the countArray variable, pushes and Return). Each countup call is independent, the fact that one is on if does not prevent the other from being on Else
– hkotsubo
@Brunovalle I updated the answer, added a more detailed explanation at the end. See if it helped you understand better
– hkotsubo
@Brunovalle If the answer solved your problem, you can accept it, see here how and why to do it. It is not mandatory, but it is a good practice of the site, to indicate to future visitors that it solved the problem. And when I get 15 points, you can also vote in all the answers you found useful. As for being a teacher, Hmmm, I think not (it is a very undervalued profession and usually does not compensate for all the stress) :-)
– hkotsubo
I get it! Everything is inside the independent calls! However, when n = 2, when it subtracts n to put 1 and then the number 2 in the array?
– Bruno Valle
I understood that until the part that is returned an array for countArray and then the function follows its flow normally. However, when placing, for example, the number 2 in the N, the correct one would be to insert the number 2 in the array, no?
– Bruno Valle
@Brunovalle
countup(2)
will enter theelse
and callconst countArray = countup(1)
(and for the above explanation, we already know thatcountup(1)
flamecountup(0)
and in the end returns[1]
). Then aftercountup(1)
returns, the variablecountArray
(within the callcountup(2)
) is[1]
. Then she calls thepush
and adds the 2 in the array (thepush
is called only aftercountup(1)
returns), and the result is[1, 2]
- That is to say,countup(2)
inserts 2 into the array, but only aftercountup(1)
returns– hkotsubo
@Brunovalle I added this explanation at the end of the reply
– hkotsubo