De 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 al menos no tiene una optimización de recursión de cola para métodos estáticos y aplica la forma adecuada de llamar a métodos estáticos con el compilador?
¿Por qué Java no tiene ningún soporte para la recursividad de cola?
No estoy seguro si hay alguna dificultad aquí.
Con respecto al duplicado sugerido , como lo explica Jörg W Mittag 1 :
- La otra pregunta es sobre TCO, esta sobre TRE. TRE es mucho más simple que TCO.
- Además, la otra pregunta se refiere a qué limitaciones impone la JVM a las implementaciones de lenguaje que desean compilar a la JVM, esta pregunta se refiere a Java, que es el único idioma que no está restringido por la JVM, ya que la especificación de la JVM puede ser modificada 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 GOTO intramétodo, que es todo lo que se necesita para TRE
1 Formato agregado para llamar los puntos realizados.
Respuestas:
Como lo explicó Brian Goetz (Java Language Architect en Oracle) en este video :
Cualquier cosa que cambiara el número 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.
Además, menciona que no es una prioridad, sino que la recursión de la cola
Nota: Esto se aplica a HotSpot y OpenJDK, otras máquinas virtuales pueden variar.
fuente
Java no tiene una 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 cola con bucles imperativos. La complejidad no vale la pena para una característica cuyo uso se desaconseja como una cuestión de estilo.
Esto en el que los programadores quieren escribir a veces en un estilo FP en lenguajes imperativos solo entró en boga en los últimos 10 años más o menos, después de que las computadoras comenzaron a escalar en núcleos en lugar de GHz. Incluso ahora, no es tan popular. Si sugiero reemplazar un bucle imperativo con una recursión de cola en el trabajo, la mitad de los revisores del código se reirían y la otra mitad daría una mirada confusa. Incluso en la programación funcional, generalmente evita la recursión de cola a menos que otras construcciones como las funciones de orden superior no se ajusten perfectamente.
fuente
for
bucle" (y de la misma manera para funciones de primera clase frente a objetos). No iría tan lejos como para llamarlo "intolerancia imperativa", pero no creo que hubiera tenido una gran demanda en 1995, cuando la principal preocupación era probablemente la velocidad de Java y la falta de genéricos.Java no tiene una optimización de llamadas altas porque la JVM no tiene un código de bytes para las llamadas de cola (a algún puntero de función estáticamente desconocido , por ejemplo, un método en alguna vtable).
Parece que por razones sociales (y quizás técnicas), agregar una nueva operación de bytecode en la JVM (lo que lo haría incompatible con versiones anteriores de esa JVM) es terriblemente difícil para el propietario de la especificación JVM.
Las razones técnicas para no agregar un nuevo código de bytes en la especificación JVM incluyen el hecho de que las implementaciones JVM de la vida real son piezas de software terriblemente complejas (por ejemplo, debido a las muchas optimizaciones JIT que está haciendo).
Las llamadas de cola a alguna función desconocida requieren reemplazar el marco de pila actual por uno nuevo, y esa operación debe ubicarse en la JVM (no se trata solo de cambiar el compilador generador de bytecode).
fuente
A menos que un idioma tenga una sintaxis especial para hacer una llamada de cola (recursiva o no) y un compilador graznará cuando se solicite una llamada de cola pero no se pueda generar, la optimización de "cola" o recursión de cola "opcional" generará situaciones en las que una pieza 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. Tal diferencia debería considerarse cualitativa más que simplemente cuantitativa.
Se espera que las máquinas puedan tener diferentes tamaños de pila y, por lo tanto, siempre es posible que el código funcione en una máquina, pero sople la pila en otra. En general, sin embargo, el código que funcionará en una máquina incluso cuando la pila está artificialmente restringida probablemente funcionará en todas las máquinas con tamaños de pila "normales". Sin embargo, si un método que tiene una profundidad de 1,000,000 es optimizado 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 fallará en la segunda incluso si su pila es inusualmente grande .
fuente
Creo que la recursión de llamadas de cola no se usa en Java principalmente porque hacerlo alteraría los rastros de la pila y, por lo tanto, haría que la depuración de un programa sea mucho más difícil. Creo que uno de los objetivos principales de Java es permitir que los programadores depuren 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. Dado que la iteración podría usarse en su lugar, el comité de idiomas debe haber pensado que no vale la pena agregar una recursión de cola.
fuente