Suppose I have this simple JavaScript function:
function returnArray(){
return [1, 2, 3];
}
Further suppose that I then say
<
Just a minor change:
function double(array) {
// note the return here is an array, not a number
if (array.length === 1) return [2 * array[0]];
var [num, ...rest] = array;
if (rest.length) return [2 * num, ...double(rest)];
}
console.log(double([1, 2, 3, 4]));
You were returning a number, and destructuring a number will leave you with an error.
...5 // throws SyntaxError
Here is the error I get using node@6.10.3
if (rest.length!=0) return [2*num, ...double(rest)];
^
TypeError: double(...)[Symbol.iterator] is not a function
at double (/home/henrique/labs/test.js:4:41)
at double (/home/henrique/labs/test.js:4:41)
at Object.<anonymous> (/home/henrique/labs/test.js:7:1)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:390:7)
Which probably means that the result of the evaluation of some of your function call is not an iterable.
The error is here:
if (array.length===1) return 2*array[0];
Change to:
if (array.length===1) return [2*array[0]];
and it will work.
It's a very strange error message, no question, but the main problem is a logical error in double
: In two branches of the code, calling double
results in a non-iterable value (in one case a number, in another undefined
). But you're always applying spread notation to it. So that fails in those two cases.
The cases are:
array.length === 1
case.array.length
is not 1 and rest.length
is 0, so the result of calling double
in that case is undefined
.You're hitting the case where you try to spread a number first, like this:
function a() {
return 42;
}
const b = [...a()];
For #1, you should be returning an array with one entry. For #2, You should be returning []
. So the minimal changes version is:
function double(array) {
if (array.length === 1) {
return [2*array[0]];
// ^−−−−−−−−−−^−−−−−−−−−−− note
}
var [num, ...rest] = array;
if (rest.length > 0) {
return [2*num, ...double(rest)];
}
return []; // <−−−−−−−−−−−−−−−−− note
}
console.log(double([1,2,3]));
Your logical error has been pointed out in comments and answers, but let me point out a cleaner, simpler, less bug-prone way to write this which is more in line with basic principles of recursion.
function double([head, ...tail]) {
if (head === undefined) return [];
return [2*head, ...double(tail)];
}
In other words, there is only one "base case", namely the empty array, which returns an empty array. Everything else is simple recursion.
You could "functionalize" this further with
function map(fn) {
return function iter([head, ...tail]) {
return head === undefined ? [] : [fn(head), ...iter(tail)];
};
}
const double = map(x => 2*x);
console.log(double([1, 2, 3]));