Reputation: 55729
I have written a function to sum values recursively, but it does not meet the criteria for tail call optimization in ES6 (for reasons I cannot articulate).
function sum(...values) {
if(!values.length) {
return 0;
}
return values.shift() + sum(...values);
}
How can I change it to be eligible for optimization?
Upvotes: 3
Views: 451
Reputation: 664548
You need to do
return sum(…);
to make a proper tail call. In your example, the +
operation is still executed after the recursive call, which makes this not work.
The typical approach is to use a helper function with an accumulator parameter:
function sum(...values) {
function sumTo(acc, values) {
if (!values.length) return acc;
else return sumTo(acc+values.shift(), values); // tail-recursive call
}
return sumTo(0, values);
}
When recursing over lists, you can also (ab)use the list itself:
function sum(...values) {
switch (values.length) {
case 0: return 0;
case 1: return values[0];
default: values.unshift(values.shift()+values.shift());
return sum(...values);
}
}
// or alternatively:
function sum(acc, ...values) {
switch (arguments.length) {
case 0: return 0;
case 1: return acc;
default: values[0] += acc;
return sum(...values);
}
}
Upvotes: 6