Нет, Ruby не выполняет TCO. Однако он также не не выполняет TCO.
Спецификация языка Ruby не говорит ничего о TCO. Он не говорит, что вам нужно это делать, но он также не говорит вам, что не может сделать это. Вы просто не можете rely на нем.
Это в отличие от схемы, где Спецификация языка требует что все Реализации должны выполнять TCO. Но это также не похоже на Python, где Guido van Rossum очень много раз делал (в последний раз всего пару дней назад), что Python Implementations не должен выполнять TCO.
Yukihiro Matsumoto сочувствует TCO, он просто не хочет принуждать все Реализации для его поддержки. К сожалению, это означает, что вы не можете полагаться на TCO, или если вы это сделаете, ваш код больше не будет переносимым для других Ruby-реализаций.
Итак, некоторые Ruby Implementations выполняют TCO, но большинство из них этого не делают. Например, YARV поддерживает TCO, хотя (на данный момент) вы должны явно раскомментировать строку в исходном коде и перекомпилировать виртуальную машину, чтобы активировать TCO - в будущих версиях она будет включена по умолчанию, после того, как реализация докажет стабильный. Виртуальная машина Parrot поддерживает TCO изначально, поэтому кардинал тоже вполне мог ее поддержать. CLR поддерживает некоторую поддержку TCO, что означает, что IronRuby и Ruby.NET могли бы это сделать. Возможно, Рубиний тоже мог бы это сделать.
Но JRuby и XRuby не поддерживают TCO, и они, вероятно, не будут, если только JVM не получит поддержку TCO. Проблема заключается в следующем: если вы хотите иметь быструю реализацию и быструю и плавную интеграцию с Java, тогда вы должны быть совместимы с Java и использовать стек JVM как можно больше. Вы можете с легкостью реализовать TCO с батутами или явным стилем продолжения прохождения, но тогда вы больше не используете стек JVM, а это означает, что каждый раз, когда вы хотите позвонить в Java или вызвать Java в Ruby, вам нужно выполнить какой-то конверсия, которая медленная. Итак, XRuby и JRuby решили пойти со скоростью и интеграцией Java по TCO и продолжениям (которые в основном имеют ту же проблему).
Это относится ко всем реализациям Ruby, которые хотят тесно интегрироваться с некоторой платформой хоста, которая не поддерживает TCO изначально. Например, я предполагаю, что у MacRuby будет такая же проблема.
Возможно, я ошибаюсь (пожалуйста, просветите меня, если да), но я сомневаюсь, что TCO имеет смысл в истинных языках OO, так как хвостовой вызов должен иметь возможность повторно использовать рамку стека вызывающего абонента. Поскольку с поздним связыванием во время компиляции не известно, какой метод будет вызван отправкой сообщения, представляется трудным гарантировать, что (возможно, с помощью JIT с обратной связью по типу или путем принудительного использования всеми разработчиками сообщения кадров стека одного размера или путем ограничения TCO на самоотходы одного и того же сообщения ...). –
Это отличный ответ. Эта информация не легко найти через Google. Интересно, что yarv поддерживает его. –
Damien, оказывается, что TCO на самом деле * требуется * для истинных языков OO: см. Http://projectfortress.sun.com/Projects/Community/blog/ObjectOrientedTailRecursion. Не волнуйтесь слишком много о материале фрейма стеллажа: вполне возможно правильно спроектировать рамки стека, чтобы они хорошо работали с TCO. –