Se optimizan las llamadas finales en Frege. Sé que no hay TCO ni en Java ni en lenguajes que compilan códigos de byte JVM como Clojure y Scala. ¿Qué hay de Frege?¿Frege realiza la optimización de la cola de llamada?
Respuesta
Frege does Tail Recursion Optimization simplemente generando while loops.
Las llamadas de cola generales se manejan "por cierto" a través de la pereza. Si el compilador ve una llamada final a una función sospechosa que se sabe que es (indirectamente) recursiva, se devuelve un resultado diferido (un thunk). Por lo tanto, la carga real de llamar a esa función recae en la persona que llama. De esta forma, se evitan las pilas cuya profundidad depende de los datos.
Dicho esto, ya la profundidad de la pila estática es por naturaleza más profunda en un lenguaje funcional que en Java. Por lo tanto, algunos programas necesitarán tener una pila más grande (es decir, con -Xss1m).
Existen casos patológicos, en los que se generan grandes thunks y cuando se evalúan, se produce un desbordamiento de la pila. Un ejemplo notorio es la función foldl (el mismo problema que en Haskell). Por lo tanto, el plegado a la izquierda estándar en Frege es plegado, que es recursivo de cola y estricto en el acumulador y, por lo tanto, trabaja en un espacio de pila constante (como Haskells foldl ').
El siguiente programa debe no desbordamiento de pila, pero la impresión "falsa" después de 2 ó 3 años:
module Test
-- inline (odd)
where
even 0 = true
even 1 = false
even n = odd (pred n)
odd n = even (pred n)
main args = println (even 123_456_789)
Esto funciona de la siguiente manera: println debe tener un valor de imprimir, por lo que trata de evaluar (incluso n) Pero todo lo que obtiene es un golpe a (impar (pred n)). Por lo tanto, trata de evaluar este procesador, que recibe otro procesador (even (pred (pred n))). incluso debe evaluar (pred (pred n)) para ver si el argumento fue 0 o 1, antes de devolver otro procesador (impar (pred (n-2)) donde n-2 ya está evaluado. De esta manera, todas las llamadas (en el nivel JVM) se hace desde println. En ningún momento incluso se invoca impar, o viceversa.
Si uno descomenta la directiva en línea, uno obtiene una versión recursiva de cola, y el resultado se obtiene diez veces . rápido
hace falta decir que este algoritmo torpe es sólo para demostración -. normalmente uno se compruebe si-dad incluso con una operación de bit
Aquí es otra versión, que es patológico y se apilarán overflo w:
even 0 = true
even 1 = false
even n = not . odd $ n
odd = even . pred
El problema aquí es que not
es la llamada de cola y es estricta en su argumento (es decir, para negar algo, primero debe tener ese algo). Por lo tanto, cuando se calcula even n
, entonces not
debe evaluar completamente odd n
que, a su vez, debe evaluar completamente even (pred n)
y por lo tanto tomará 2 * n marcos de pila.
Lamentablemente, esto no va a cambiar, incluso si la JVM debe tener la cola adecuada un día. La razón es la recursión en el argumento de una función estricta.
¡Respuesta increíble, muchas gracias! Por cierto, ¿hay anotaciones de rigor en Frege? – haskelline
Sí. Patrones de explosión – Ingo
@Landei TCO no se admite por completo en Scala ... prueba este.
def foo() { def bar() { println("bar"); foo() }; println("foo"); bar() }
Nota, no tengo suficiente reputación para comentar directamente. Encontrar comentario Estoy respondiendo en los comentarios de la pregunta original.
- 1. ¿MATLAB realiza la optimización de la cola de llamada?
- 2. ¿Ruby realiza optimización de llamadas de cola?
- 3. ¿array_walk_recursive utiliza la optimización de la cola de cola?
- 4. C optimización de llamadas de cola
- 5. optimización de llamadas de cola en Mathematica?
- 6. ¿Qué hilo ejecuta la devolución de llamada cuando se realiza una llamada de Servicios RIA asíncrona?
- 7. ¿Scala es compatible con la optimización de la recursividad de cola?
- 8. Intel C++ Compiler comprensión de lo que la optimización se realiza
- 9. Falló la devolución de llamada llamada aunque se realiza la solicitud Ajax y el servidor devuelve 200 con datos
- 10. Optimización de la memoria Redis
- 11. ¿Por qué el compilador de Scala no aplicará la optimización de la cola de cola a menos que un método sea definitivo?
- 12. ¿Dónde se realiza la validación?
- 13. ¿Cómo se realiza la validación de dirección?
- 14. ¿Dónde se realiza la anulación de funciones?
- 15. Optimización de la creación de entorno Jinja2
- 16. ¿Cómo realiza Minecraft la iluminación?
- 17. Mover el mensaje de la cola de la carta muerta a la cola de salida MSMQ
- 18. JERSEY: ¿Cómo recuperar la IP o el URI que realiza la llamada utilizando la anotación de inyección?
- 19. Explícame cuál es el gran problema con la optimización de la cola de llamadas y por qué Python lo necesita
- 20. Obtengo una StackOverFlowException en este código porque mi JVM no es compatible con la optimización de llamadas de cola, ¿verdad?
- 21. Optimización de la manipulación de la secuencia F #
- 22. Optimización de Java: variable local o llamada de función
- 23. Ordenando una cola usando la misma cola
- 24. ¿Evita la JVM las optimizaciones de cola?
- 25. ¿Cuál es la diferencia entre la "cola global" y la "cola principal" en GCD?
- 26. VS2010 C++ optimización
- 27. Optimización de una fórmula llamada SQL en PHP haversine
- 28. ¿GHC puede realizar una llamada de cola para optimizar las acciones de E/S?
- 29. Control programático de la optimización de Python?
- 30. optimización de la velocidad de consulta mysql
El título de su pregunta es lo primero que la gente ve, y "TCO" es solo otro TLA. –
Cabe mencionar que Scala tiene TCO y que algunas JVM (como la de IBM) también lo implementan. – Landei
@Landei es esta una nueva característica en Scala? TCO no se admite en Scala desde hace mucho tiempo. – haskelline