No, Ruby no realiza TCO. Sin embargo, tampoco realiza el TCO.
La especificación del lenguaje Ruby no dice nada sobre el TCO. No dice que tengas que hacerlo, pero tampoco dice que no puedas hacerlo. Simplemente no puedes confiar en eso.
Esto es diferente a Scheme, donde la especificación de lenguaje requiere que todas las implementaciones deben realizar TCO. Pero también es diferente de Python, donde Guido van Rossum ha dejado muy claro en múltiples ocasiones (la última vez hace un par de días) que las implementaciones de Python no deberían realizar TCO.
Yukihiro Matsumoto simpatiza con TCO, simplemente no quiere forzar todos implementaciones a que lo respalden. Desafortunadamente, esto significa que no puede confiar en el TCO o, si lo hace, su código ya no será portátil a otras implementaciones de Ruby.
Por lo tanto, algunas implementaciones de Ruby realizan TCO, pero la mayoría no. YARV, por ejemplo, es compatible con TCO, aunque (por el momento) debe descomentar explícitamente una línea en el código fuente y volver a compilar la VM para activar el TCO; en futuras versiones estará activado de forma predeterminada, una vez que la implementación lo demuestre. estable. Parrot Virtual Machine admite TCO de forma nativa, por lo que Cardinal también podría admitirlo con bastante facilidad. El CLR tiene cierto soporte para TCO, lo que significa que IronRuby y Ruby.NET probablemente podrían hacerlo. Probablemente Rubinius también podría hacerlo.
Pero JRuby y XRuby no admiten TCO, y probablemente no lo harán, a menos que la propia JVM obtenga soporte para TCO. El problema es este: si desea tener una implementación rápida y una integración rápida y sin problemas con Java, entonces debe ser compatible con Java y usar la pila de JVM tanto como sea posible. Puede implementar TCO con bastante facilidad con trampolines o un estilo de paso de continuación explícito, pero luego ya no está utilizando la pila JVM, lo que significa que cada vez que desea llamar a Java o llamar desde Java a Ruby, debe realizar algún tipo de conversión, que es lenta. Entonces, XRuby y JRuby optaron por la velocidad y la integración de Java sobre el TCO y las continuaciones (que básicamente tienen el mismo problema).
Esto se aplica a todas las implementaciones de Ruby que desean integrarse estrechamente con alguna plataforma de host que no admite TCO de forma nativa. Por ejemplo, supongo que MacRuby tendrá el mismo problema.
Actualización: Aquí hay una buena explicación del TCO en Ruby: http://nithinbekal.com/posts/ruby-tco/
Actualización: es posible que también desee consultar la gema tco_method : http://blog.tdg5.com/introducing-the-tco_method-gem/
En Ruby MRI (1.9, 2.0 y 2.1) puede activar el TCO con:
Hubo una propuesta para activar el TCO de forma predeterminada en Ruby 2.0. También explica algunos problemas que vienen con eso: Optimización de la llamada de cola: ¿habilitar por defecto ?.
Extracto breve del enlace:
fuente
Puede tener, pero no se garantiza que lo haga:
https://bugs.ruby-lang.org/issues/1256
fuente
El TCO también se puede compilar ajustando un par de variables en vm_opts.h antes de compilar: https://github.com/ruby/ruby/blob/trunk/vm_opts.h#L21
fuente
Esto se basa en las respuestas de Jörg y Ernest. Básicamente depende de la implementación.
No pude conseguir que la respuesta de Ernest funcionara en la resonancia magnética, pero es factible. Encontré este ejemplo que funciona para MRI 1.9 a 2.1. Esto debería imprimir un número muy grande. Si no establece la opción TCO en verdadero, debería aparecer el error "stack too deep".
fuente