yourself type lists learn intercalate example argument perl haskell recursion

perl - type - syntax record haskell



¿Por qué Perl tiene tanto miedo a la "recursión profunda"? (3)

Hace poco me topé con el libro Higher-order Perl , que básicamente sugiere maneras de hacer las cosas en Perl de una manera funcional. El autor explica que Perl tiene 6 de 7 funciones principales de Lisp , mientras que C no tiene ninguna.

Tuve un problema que parecía un buen candidato para una solución recursiva, y lo codifiqué de esta manera. Pero Perl se quejó de "recursión profunda". Busqué en Google un poco y encontré a un monje de Perl explicando que "Perl no es Haskell". Aparentemente obtienes una queja por defecto, cuando la profundidad de recursión supera los 100 niveles.

Hay formas de ampliar este límite o apagarlo por completo, pero mi pregunta es:

  • ¿Hay alguna razón por la cual Perl sea tan tenso con la recursión, mientras que Haskell no lo es?

El límite predeterminado es demasiado bajo, pero fue apropiado para las máquinas más pequeñas en las que Perl se ejecutó originalmente. Ahora 100 es risible si estás haciendo un trabajo recursivo serio, pero como dices, puede ajustarse. ¿Supongo que Haskell tiene alguna otra forma de captar la recursión infinita?


La advertencia de "recursión profunda" es opcional y un indicador de que algo pudo haber salido mal: la mayoría de las veces, una función que se llama a sí misma una y otra vez no es intencional (Perl es un lenguaje multi-paradigmático, y muchas personas no usar modismos funcionales). E incluso cuando conscientemente emplea recursividad, es demasiado fácil olvidar el caso base.

Es fácil desactivar la advertencia de "recursión profunda":

use warnings; no warnings ''recursion''; sub recurse { my $n = shift; if ($n) { recurse($n - 1); } else { print "look, no warnings/n"; } } recurse(200);

Salida:

look, no warnings

Es cierto que Perl no realiza la optimización de la recursividad de la cola, porque eso arruinaría la salida de la caller que caller (que es vital para algunas cosas como pragmas o Carp ). Si desea realizar manualmente una llamada de cola, entonces

return foo(@args);

se convierte

@_ = @args; # or something like `*_ = /@args` goto &foo;

aunque pueden suceder cosas malas si tontamente local @_ .


Porque en Haskell, tenemos la holgazanería y la recursión cautelosa y la optimización de la cola de llamada, y Perl no tiene ninguno.

Esto significa esencialmente que cada llamada de función asigna una cantidad establecida de memoria llamada "la pila" hasta que la función regrese. Cuando escribe código recursivo, crea una gran cantidad de memoria debido a estas llamadas a funciones anidadas y, finalmente, puede acumular desbordamiento. TCO permite que los fragmentos no utilizados se optimicen lejos.

Sin esto, no es realmente una buena idea confiar en la recursión. Por ejemplo, digamos que usted escribió una versión recursiva del map , se estrellaría con cualquier lista de tamaño decente. En Haskell, la recursión protegida significa que con grandes listas, la solución recursiva es mucho más rápida que una función tipo "bucle".

TLDR: las implementaciones de Haskell están diseñadas para manejar un estilo funcional / recursivo y la implementación de Perl no lo es y en los viejos tiempos, 100 niveles de llamadas a funciones era un límite razonable.