Reputation: 81
I'm working to wrap my head around recursion and maybe I'm being too obsessive, but here goes:
In the javascript code
var factorial = function(number) {
// If the number is negative, it doesn't have a factorial. Return an
// impossible value to indicate this.
if (number < 0) {
return -1;
}
// If the number is zero, its factorial is one.
if (number === 0) {
return 1;
}
// If the number is neither illegal nor zero, call factorial again,
// this time passing in a smaller number. Eventually we'll reach 0,
// causing each call to return to its caller and the recursion terminates.
return number * factorial(number - 1);
};
factorial(5);
The recursive function returns 120 as expected, but why?
In drawing out the logic, 2 things trip me up: 1) Why is this even operable and 2) Though it is operable, why wouldn't it return -1?
1) Why is this even operable?:
In drawing this out and plugging 5 as an argument, in the return statement at the bottom, we get return 5 * factorial(5 - 1). Why does this equate to 20 as expected? Aren't we calling the function to return 5 * the value of factorial(5-1)? How can we multiply 5 by the value of something that hasn't even been determined yet? If this was simply 5 * (5-1) = 20, then that's obvious or even factorial(5) * (5-1) = 20 makes sense..
2)Though it is operable, why doesn't it return -1?:
As with the case above, eventually, we'll get to the point in the recursion where it'll look like 1 * factorial(1-1)... 1 * (1-1) = 0. And with this function plugging the number in to itself for operation, and with our base case saying "if the integer plugged in is zero, stop operation and return -1". Why isn't that happening here?
Apologies if this seems simple, I may be making it a bigger deal than in needs to be. I just want to learn :) .
Upvotes: 0
Views: 283
Reputation: 3424
To add to winhowes' answer
How can we multiply 5 by the value of something that hasn't even been determined yet?
Well, we don't, not until we know the value of factorial(5-1)
. When factorial(5-1)
is called, we don't actually do the multiplication yet, until we have a definite answer for that. So the 5 stays there and waits for the result of the function call to come back, but then the 4 also waits for factorial(4-1)
.. etc. Once the final call (i.e. factorial(1)
) returns a definitive answer, it multiplies by whatever was waiting for it, and that in turn goes and multiplies with the previous waiting call.
So you have a top-down call of methods, and when you have the values, a bottom-up of multiplications occur. As illustrated in this diagram:
Upvotes: 2
Reputation: 8065
Great question - glad you're diving into recursion head on!
Let's walk through what's going on:
We start with factorial(5)
. This returns 5 * factorial(5-1)
as you pointed out. In order to understand what factorial(5-1)
is, we have to call the factorial
function again.
factorial(5-1)
returns 4 * factorial(4-1)
. Let's substitute that in to what we have above. That gives us 5 * 4 * factorial(4-1)
. Again we do factorial(4-1)
and substitute that in. Which gives us 5 * 4 * 3 * factorial(3-1)
.
If we continue we get 5 * 4 * 3 * 2 * factorial(2-1)
and then 5 * 4 * 3 * 2 * 1 * factorial(1-1)
.
Now something different happens here. factorial(1-1)
returns 1
per the if condition:
// If the number is zero, its factorial is one.
if (number === 0) {
return 1;
}
So we have 5 * 4 * 3 * 2 * 1 * 1
which = 120 = 5! as we expect. We're never going to hit the number == -1
if condition unless we put in a negative number. For any positive number, the number == 0
condition will catch every time.
Upvotes: 2