Как изменить этот код для включения оптимизации хвостового вызова в ES6?

Я написал функцию для рекурсивного суммирования значений, но она не соответствует критериям оптимизации хвостового вызова в ES6 (по причинам, которые я не могу сформулировать).

function sum(...values) {
  if(!values.length) { 
    return 0; 
  }
  return values.shift() + sum(...values);
}

Как я могу изменить его, чтобы иметь право на оптимизацию?

1 ответ

Решение

Вам нужно сделать

return sum(…);

сделать правильный хвостовой вызов. В вашем примере + операция все еще выполняется после рекурсивного вызова, что делает это неработоспособным.

Типичный подход заключается в использовании вспомогательной функции с параметром аккумулятора:

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

Повторяя списки, вы также можете (ab) использовать сам список:

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);
    }
}
Другие вопросы по тегам