Одной из новых функций ES2015 (ES6) являются правильные хвостовые вызовы (PTC). Несмотря на то, что это указано в первой строке Таблицы совместимости ES6, еще не многие браузеры/среды выполнения реализуют это. Среди них Safari 10, выпущенный в прошлом месяце, который включает поддержку PTC.

PTC по библиотеке

Около четырех лет назад я разработал библиотеку под названием continuation.js. Это поддерживает PTC, преобразовывая код JavaScript, который имеет рекурсивные хвостовые вызовы, в код JavaScript, устраняя эти рекурсивные хвостовые вызовы. Моей мотивацией было написать код JavaScript, такой как Scheme, а для этого требуется PTC. Однако преобразование является дорогостоящим, а результирующий код не очень эффективен и быстр. Итак, я с нетерпением жду встроенной поддержки PTC.

Давай попробуем

Вы можете просто попробовать запустить код в консоли Web Inspector. Единственное, что нужно учитывать, это то, что он должен запускаться в режиме скрипта [1].

function fact(x) {
  'use strict';
  function fact_tail(x, r) {
    if (x === 0) {
      return r;
    } else {
      return fact_tail(x — 1, x * r);
    }
  }
  return fact_tail(x, 1);
}

Выше приведена функция для вычисления факториала.

> fact(100000)
VM212:2 Uncaught RangeError: Maximum call stack size exceeded(…)

Это выше результат запуска в Chrome 53.

> fact(100000)
Infinity

Выше показан результат в Safari 10. Хотя результат Infinity совсем не интересен, расчет завершен без ошибки размера стека.

Ниже приведен еще один пример, который называется «взаимная рекурсия».

function isEven(x) {
  'use strict';
  if (x === 0) {
    return true;
  } else {
    return isOdd(x - 1);
  }
}
function isOdd(x) {
  'use strict';
  if (x === 0) {
    return false;
  } else {
    return isEven(x - 1);
  }
}

// the results follow:
[In Chrome 53]
> isOdd(1234567)
VM3306:10 Uncaught RangeError: Maximum call stack size exceeded(…)
[In Safari 10]
> isOdd(1234567)
true

Опять же, приведенный выше пример не очень причудлив, но дело в том, не сработает ли он с ошибкой размера стека или нет.

Резюме

Ну, я просто хотел проверить, действительно ли Safari 10 выполняет мои старые примеры, и результат успешен. В будущем возможные темы о PTC могут касаться сравнения производительности и практического использования.