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);
}
}