История изменений
Исправление
dave,
(текущая версия)
:
Часть 13.2. Английский текст про оптимизацию хвостового вызова корректен, но его можно истолковать неверно, что, кажется, и произошло в русском переводе. Есть очень распространенное заблуждение. Многие не понимают простой вещи. Хвостовой вызов действительно можно преобразовать в цикл, как это показано в PAIP, но это не значит, что это должен быть цикл самого языка высокого уровня. Но можно построить абстрактную машину, где любой хвостовой вызов фактически превращается в цикл.
Прямой хвостовой вызов обычно преобразуется в цикл самого языка. Так сделано в Scala и во многих компиляторах Common Lisp. Кажется, даже GCC умеет.
С косвенным хвостовым вызовом все сложнее, когда рекурсивный вызов передается через лямбду. Для F#, например, нужны извраты на уровне виртуальной машины CLR. Но упомянутый мною выше PAIP Питера Норвига показывает, что все могло бы быть гораздо проще, будь другим соглашение о вызовах функций.
Из общелиспов по моим наблюдениям и тестам только SBCL умеет оптимизировать косвенный хвостовой вызов.
Исходная версия
dave,
:
Часть 13.2. Английский текст про оптимизацию хвостового вызова корректен, но его можно истолковать неверно, что, кажется, и произошло в русском переводе. Есть очень распространенное заблуждение. Многие не понимают простой вещи. Хвостовой вызов действительно можно преобразовать в цикл, как это показано в PAIP, но это не значит, что это должен быть цикл самого языка высокого уровня. Но можно построить абстрактную машину, где любой хвостовой вызов фактически превращается в цикл.
Прямой хвостовой вызов обычно преобразуется в цикл самого языка. Так сделано в Scala и во многих компиляторах Common Lisp. Кажется, даже GCC умеет.
С косвенным хвостовым вызовом все сложнее, когда рекурсивный вызов передается через лямбду. Для F#, например, нужны извраты на уровне виртуальной машины CLR. Но упомянутый мною выше PAIP Питера Норвига показывает, что все могло бы быть гораздо проще, будь другим соглашение о вызовах функций.