У меня есть хвостовой рекурсивный алгоритм поиска пути, который я реализовал в Javascript, и хотел бы знать, могут ли какие-либо (все?) браузеры получить исключения.
Оптимизированы ли хвосты для Javascript-двигателей?
Ответ 1
Спецификация ECMAScript 4 изначально собиралась добавить поддержку TCO, но она была удалена.
http://lambda-the-ultimate.org/node/3047
Насколько я знаю, широкодоступные реализации JS в настоящее время не выполняют автоматическую TCO. Это может быть полезно для вас:
http://www.paulbarry.com/articles/2009/08/30/tail-call-optimization
По существу, использование шаблона аккумулятора выполняет тот же эффект.
Ответ 2
На данный момент нет радости, но, к счастью, правильные хвостовые звонки намечены для Harmony (ECMAScript версии 6) http://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls
Ответ 3
Практически каждый браузер, с которым вы столкнулись, будет "слишком рекурсивно". Здесь находится запись в трекере V8, которая, вероятно, будет интересна для чтения.
Если это простая саморегуляция, вероятно, стоит попытаться использовать явную итерацию, а не надеяться на устранение хвостового вызова.
Ответ 4
Оптимизация вызовов в хвосте будет поддерживаться в строгом режиме ECMAScript 6 в будущем. Проверьте http://www.2ality.com/2015/06/tail-call-optimization.html для деталей.
Проверьте http://kangax.github.io/compat-table/es6/ для текущей поддержки двигателя.
На данный момент (18-07-2019) следующие механизмы поддерживают оптимизацию хвостовых вызовов:
- Safari> = 10
- iOS> = 10
- Кинома XS6
- Duktape 2.3
поддержка, если включены "экспериментальные функции JavaScript" -flag:
- Узел 6.5
-
Chrome 54/Opera 41Текущая версия таблицы сравнения больше не содержит ее
Ответ 5
Оптимизация звонков теперь доступна в LispyScript, который компилируется в javascript. Вы можете прочитать об этом здесь.
Ответ 6
В настоящее время реализация JS не распознает хвостовую рекурсию. Изменения приводятся в ECMAScript 6, и, как говорили другие, есть открытый билет на V8
Здесь вы можете увидеть V8 сгенерированный ассемблер для функции рекурсии хвоста
https://gist.github.com/mcfedr/832e3553964a014621d5
Сравните это с тем, как clang скомпилировал ту же функцию в C
https://gist.github.com/mcfedr/63ad08370d856bad3694
V8 сохраняет рекурсивный вызов, тогда как компилятор C распознал хвостовую рекурсию и изменил ее на цикл