Reputation: 19642
Why does the following javascript factorial function throw a stack overflow error when called?
function fact(n) {
return function () {
var n = n;
return (n < 2) ? 1 : (n*fact(n - 1));
}();
};
When I remove the line var n = n;
it works as expected. Also, I'm aware that the inner function is redundant, it's just there to trigger the error.
Upvotes: 1
Views: 324
Reputation:
You only need to omit the re-declaration of var n
and the code is working fine. But i would go for a for
loop in this one, it makes half the time.
function fact(n) {
return function () {
return (n < 2) ? 1 : (n*fact(n - 1));
}();
};
let startDate = performance.now();
console.log(fact(170),`fact(170) took: ${(performance.now()-startDate)} milliseconds`);
function fact2(n) {
let result = 1;
for(let i = 2; i <=n; i++) {
result *= i;
}
return result;
}
startDate = performance.now();
console.log(fact2(170),`fact2(170) took: ${(performance.now()-startDate)} milliseconds`);
PS: the timing was made out of curiosity. I wanted to see a difference between the timed needed in this answer on a somehow relative answer that involved Julia
programming language.
Upvotes: 0
Reputation: 367
The line var n = n;
isn't necessary, because it's defining a 'new' variable called n
, and setting it to n
.
Your function is returning the result from an anonymous function, which isn't necessary.
The parameter n
is in the main function, not the anonymous function.
I also spaced the *
symbol, in (n*fact(n - 1))
The original code:
function fact(n) {
return function () {
var n = n;
return (n < 2) ? 1 : (n*fact(n - 1));
}();
};
The updated code:
function fact(n) {
return (n < 2) ? 1 : (n * fact(n - 1));
};
Upvotes: 1
Reputation: 140228
var n = n
in that situation effectively does n = undefined
because the formal parameter n
and the declared n
are from different scopes. In your comment declaration n
and formal parameter n
are in same scope so it's not the same situation.
undefined < 2
is always false, so it keeps calling fact
forever.
Upvotes: 8
Reputation: 122936
@Esailija already explained the cause. Try:
function fact(n) {
return function(n) {return n && n > 1 && n*(fact(n-1)) || 1;}(n);
// ^ pass n here
};
Or use the closure:
function fact(n) {
return function() {return n && n > 1 && n*(fact(n-1)) || 1;}();
};
Or indeed just use:
function fact(n) {
return n && n > 1 && n*(fact(n-1)) || 1;
};
Upvotes: 0
Reputation: 1758
var n = n
<- two problems here.
1: You have two variable with the same name, how could they be differenciated
2: var n = n
is equal to var n = undefined
, witch result in false
return
and loop forever
What you want to do is :
function fact(n1) {
return function (n1) {
var n = n1;
return (n < 2) ? 1 : (n*fact(n - 1));
}();
};
Upvotes: 1