¿Por qué mi profesor sugiere que usemos bucles en lugar de recurrencia en el código de producción?

Cuando se llama a una función, el programa detrás de escena creará algo llamado marco de pila. El marco de la pila es donde se preserva el alcance de las variables de las funciones de llamada y se crean las variables de las funciones llamadas. Si ha estudiado lenguaje ensamblador en una de sus clases y tiene acceso a un depurador de nivel ensamblador, es muy educativo avanzar en la ejecución de la configuración y desmontar estos marcos de pila para invocar el alcance de las variables.

Estos marcos de pila se crean en una pila de llamadas de proceso. El tamaño de la pila de llamadas está limitado en Unix; la memoria asignada para la pila de llamadas se comparte con el montón. El montón es donde se almacenan las variables mallocadas y globales.

En la recursividad, se crea un marco de pila cada vez que se realiza una llamada recursiva. El número de llamadas recursivas que puede realizar depende de la memoria restante no asignada entre la parte superior de la pila de llamadas y la parte superior del montón (crecen en direcciones opuestas). De todos modos, el número de llamadas recursivas que puede hacer es limitado y si no conoce el entorno en el que está trabajando, la depuración será un infierno porque puede fallar en casos irreproducibles.

Sin embargo, si convierte su programa para usar un bucle en lugar de recurrencia, evitará los límites del sistema operativo y puede funcionar mucho más tiempo. A veces, su programa se ejecutará de manera más eficiente porque evitará la configuración del marco de llamadas y el desmantelamiento asociado con las llamadas a funciones.

Porque las funciones recursivas tienden a llamarse un buen número de veces. Hay 2 cosas malas asociadas con él.

  1. Si el número de llamadas recursivas es mayor que la pila de llamadas de función, se produce un error de desbordamiento de pila y
  2. Incluso si no es así, la sobrecarga asociada con las llamadas a funciones es mayor que ejecutar un bucle y, por eso, usar bucles es mejor para la optimización.

Hay algunos lenguajes de programación funcionales que admiten la recursividad de cola (lo que significa que la recursión puede optimizarse en una estructura de bucle si no puede pasar nada después de la llamada recursiva) como Scala y (realmente no lo sé, pero creo) elixir. Luego, el uso de la recursión no agrega la sobrecarga e inunda la pila de llamadas.

¿En qué idioma estás programando? Muchos lenguajes imperativos / orientados a objetos, como Java, no admiten muchas de las cosas que hacen que la recursión sea tan buena como el bucle (como la Optimización de llamadas de cola). Pero si está codificando en idiomas como F #, Erlang, Scala y lisp-likes, entonces la mayoría de las veces ni siquiera usa bucles. En haskell, por ejemplo, ¡la iteración simple (afaik) ni siquiera es compatible con el idioma! Como regla general, trataría de usar la recursividad (y otros mecanismos de bucle, como el mapeo / plegado con funciones de orden superior) siempre que el lenguaje lo soporte de manera eficiente, y el bucle cuando me “obligue” a hacerlo.

La recursión puede conducir a un desbordamiento de pila si el algoritmo está mal diseñado, como si usara demasiada memoria. Cada vez que el método regresa durante la recursión, todos los datos requeridos por el método se almacenan en la pila hasta que se alcanza la condición base. Usted sabe que stackoverflow puede eliminar una aplicación completa. Así que hazlo con bucles a menos que hayas diseñado tu recursión lo suficientemente bien. Algunos algoritmos basados ​​en árboles requieren recursividad y puede ver ejemplos estándar de cómo están diseñados.

Debido a que no todas las implementaciones de idiomas / idiomas admiten correctamente la recursividad, algunas usarán espacio de pila incluso cuando técnicamente no sea necesario, por lo que su programa eventualmente se bloqueará (dados los datos suficientes).

En los idiomas que admiten correctamente la recursividad, solo use lo que sea más claro. En los idiomas que no tienen bucles, es obvio lo que debe usar 🙂

PD La situación en la que no es necesario usar stack es cuando lo último que hace la función es llamar a otra función, por lo tanto, cuando no queda nada que hacer después de la llamada, y la llamada más profunda puede regresar a quien llamó al recursivo funcionar en primer lugar. Esto se llama “función recursiva de cola”, y la optimización que se necesita se llama “optimización de llamada de cola”.

La recursión es genial, divertida y puede resolver algunos problemas mucho más fácilmente que el método iterativo y el código escrito es mucho más corto …

Pero , aparte de eso, los métodos iterativos son mucho mejores para problemas de programación en tiempo real. La recursión se usa principalmente en entornos académicos.

La respuesta es bastante simple. La mayoría de las veces, los bucles son más fáciles y rápidos de entender que la recursividad, especialmente si no se lee el código que lo escribió (esto sucede en el 99,9% de los casos) y ese aspecto (qué tan rápido o lento es comprensible el código ) cuesta generalmente más que cualquier otra cosa.

Aunque me encanta la recursión.

Quizás este artículo pueda ofrecer una pista:

Gastos generales en software de computadora

Fundador de Boachsoft para proteger la inversión en software

Además, cuando escribes código, debería haber poca diferencia entre el código que escribes y el “código de producción”.

Practique buenos hábitos de programación todo el tiempo y se lo agradecerá en el futuro. Eso significa verificar si hay errores en cada llamada de función y manejarlos de una manera que tenga sentido. Puede o no incluir la creación de una política de propiedad / eliminación de “cosas” creadas.