¿Por qué Java no tiene optimización para la recursión de la cola en absoluto?

84

Por lo que he leído: la razón es porque no es fácil determinar qué método se llamará realmente ya que tenemos herencia.

Sin embargo, ¿por qué Java no tiene al menos optimización de recursión de cola para métodos estáticos y no hace cumplir la forma correcta de llamar métodos estáticos con el compilador?

¿Por qué Java no tiene soporte alguno para la recursión de la cola?

No estoy seguro de que exista alguna dificultad aquí.

Con respecto al duplicado sugerido , como se explica en Jörg W Mittag 1 :

  
  • La otra pregunta se refiere a TCO, esta a TRE. TRE es mucho más simple que TCO.
  •   
  • Además, la otra pregunta pregunta qué limitaciones impone la JVM a las implementaciones de lenguaje que desean compilar en la JVM, esta pregunta se refiere a Java, que es el único lenguaje que no está restringido por la JVM, ya que la especificación de JVM puede Será cambiado por las mismas personas que diseñan Java.
  •   
  • Y, por último, ni siquiera hay una restricción en la JVM sobre TRE, porque la JVM tiene un GOTO intra-método, que es todo lo que se necesita para TRE
  •   

1 Formato agregado para llamar los puntos creados.

    
pregunta InformedA 04.02.2015 - 09:40

5 respuestas

121

Como lo explicó Brian Goetz (Java Language Architect en Oracle) en este video :

  

en las clases jdk [...] hay varios métodos sensibles a la seguridad que dependen del conteo de marcos de pila entre el código de la biblioteca jdk y el código de llamada para averiguar quién los está llamando.

Cualquier cosa que cambiara la cantidad de cuadros en la pila rompería esto y causaría un error. Admite que esta fue una razón estúpida, por lo que los desarrolladores de JDK han reemplazado este mecanismo desde entonces.

Luego menciona que no es una prioridad, sino que la recursión de la cola

  

eventualmente se hará.

N.B. Esto se aplica a HotSpot y OpenJDK, otras VM pueden variar.

    
respondido por el ggovan 04.02.2015 - 14:35
22

Java no tiene optimización de llamadas de cola por la misma razón que la mayoría de los lenguajes imperativos no la tienen. Los bucles imperativos son el estilo preferido del lenguaje, y el programador puede reemplazar la recursión de la cola con bucles imperativos. La complejidad no vale la pena por una característica cuyo uso se desaconseja por cuestión de estilo.

Esta cosa en la que los programadores a veces escriben en un estilo de PF en lenguajes de otro modo imperativos solo se pusieron de moda en los últimos 10 años aproximadamente, después de que las computadoras empezaron a escalar en núcleos en lugar de GHz. Incluso ahora, no es tan popular. Si sugiriera reemplazar un bucle imperativo con una recursión de cola en el trabajo, la mitad de los revisores de código se reirían y la otra mitad daría un aspecto confuso. Incluso en la programación funcional, generalmente evitas la recursión de la cola a menos que otras construcciones como las funciones de orden superior no encajen limpiamente.

    
respondido por el Karl Bielefeldt 04.02.2015 - 14:17
5

Java no tiene una optimización de llamadas alta porque la JVM no tiene un bytecode para las llamadas de la cola (a algún puntero de función estáticamente desconocido , por ejemplo, un método en algún vtable).

Parece que por razones sociales (y quizás técnicas), agregar una nueva operación de bytecode en la JVM (lo que la haría incompatible con versiones anteriores de esa JVM) es terriblemente difícil para el propietario de la especificación de JVM.

Las razones técnicas para no agregar un nuevo bytecode en la especificación de JVM incluyen el hecho de que las implementaciones reales de JVM son piezas de software terriblemente complejas (por ejemplo, debido a las muchas optimizaciones de JIT que está realizando).

Las llamadas de cola a una función desconocida requieren reemplazar el marco de pila actual por uno nuevo, y esa operación debería realizarse en la JVM (no es solo una cuestión de cambiar el compilador que genera el código de bytes).

    
respondido por el Basile Starynkevitch 04.02.2015 - 14:22
4

A menos que un idioma tenga una sintaxis especial para hacer una llamada de cola (recursiva o de otro tipo) y un compilador emita un chirrido cuando se solicite una llamada de cola, pero no se puede generar, la optimización de la llamada de cola o la recursión de cola "opcional" producirá situaciones donde un fragmento de código puede requerir menos de 100 bytes de pila en una máquina, pero más de 100,000,000 bytes de pila en otra. Tan diferente debe considerarse cualitativo en lugar de meramente cuantitativo.

Se espera que las máquinas tengan diferentes tamaños de pila y, por lo tanto, siempre es posible que el código funcione en una máquina pero que la pila esté en otra. Sin embargo, en general, el código que funcionará en una máquina incluso cuando la pila esté restringida artificialmente funcionará en todas las máquinas con tamaños de pila "normales". Sin embargo, si un método que recurre a 1.000.000 de profundidad se optimiza en una máquina pero no en otra, la ejecución en la máquina anterior probablemente funcionará incluso si su pila es inusualmente pequeña, y falla en la última incluso si su pila es inusualmente grande .

    
respondido por el supercat 04.02.2015 - 23:03
1

Creo que la recursión de la llamada de cola no se usa en Java principalmente porque hacerlo alteraría los seguimientos de la pila y, por lo tanto, dificultaría mucho la depuración de un programa. Creo que uno de los objetivos principales de Java es permitir a los programadores depurar fácilmente su código, y el seguimiento de la pila es esencial para hacerlo, especialmente en un entorno de programación altamente orientado a objetos. Como la iteración se puede usar en su lugar, el comité de idiomas debe haber pensado que no vale la pena agregar la recursión de la cola.

    
respondido por el annoying_squid 07.06.2017 - 15:43

Lea otras preguntas en las etiquetas