Reputation: 3925
So, I am going through "JavaScript Allonge" and there is this function, to simulate array's .length
function:
const length = ([first, ...rest]) =>
first === undefined
? 0
: 1 + length(rest);
Now, if I re-write the function as:
var lengthy = (first, ...rest) =>
first === undefined ? 0 : 1 + lengthy(rest)
It gives, Maximum call stack size exceeded
, Why? I called my version like this:
lengthy(1)
Upvotes: 0
Views: 96
Reputation: 7593
var lengthy = ([first, ...rest]) => first === undefined ? 0 : 1 + lengthy(rest)
// lengthy gets passed ONE argument, an array
This most likely because first is never evaluating to 0 which causes an infinite loop.
length
accepts ONE argument which is an array.
lengthy
accepts an arbitrary number of arguments, and counts them, but when you are calling it recursively you are only passing it ONE.
So when lengthy
is called for the second time, ...rest
is undefined
and is passed in the recursive call to lengthy which means first
will from then on only be undefined
and cause your error.
Upvotes: 1
Reputation: 350272
You need to use the spread syntax in the recursive call, otherwise you will pass an array as first argument, and the rest argument will then be an empty array. This will go on endlessly.
So do:
var lengthy = (first, ...rest) =>
first === undefined ? 0 : 1 + lengthy(...rest);
console.log(lengthy(1,2,3,8,11));
Note that on the initial call rest is an array, which has all the remaining arguments in it. In the example above, rest will be [2,3,8,11]
. This is what the rest syntax does for you.
Now you can see how your recursive call would look of you would not spread that array again:
lengthy(rest)
...becomes
lengthy([2,3,8,11])
So now the arguments in the recursive call are:
first = [2,3,8,11]
rest = []
If you continue this analysis, you'll see the next call is with:
first = []
rest = []
And this will go on for ever.
Now with the correction lengthy(...rest)
, the actual call will be in the example:
lengthy(2,3,8,11)
... which is what you want. Now the next value of first
and rest
will be:
first = 2
rest = [3,8,11]
...etc.
Upvotes: 3
Reputation: 28757
The answer has to do with destructuring.
In the original, you have:
([first, ...rest])
In the second answer, you have:
(first, ...rest)
The original takes a single array as an argument, and destructures the array so that the first element is in first
and the remaining are in rest
.
The second does not destructure the array and plops the array that you pass in into first, leaving rest
to be an empty array. This is called recursively. And on all recursive calls to lengthy
, rest
is never empty.
Upvotes: 2