Leí varios libros y aprendí a través de la experiencia que optimizar el código hasta el punto en que es inescrutable, o encontrar una solución extremadamente rápida pero extremadamente compleja a un problema no es deseable cuando se trabaja en equipo, o incluso cuando se está trabajando. solo y tiene que entender su solución inteligente algún tiempo después.
Mi pregunta es, ¿debería tratarse la recursión de la misma manera? ¿El programador promedio entiende la recursión fácilmente y, por lo tanto, uno debería usarla con impunidad, o el programador promedio no comprende muy bien la recursión y debería alejarse de ella por el bien de la productividad general del equipo?
Sé que hay respuestas simples de "Cualquier programador que no entienda la recursión no vale la pena, así que no se preocupe por ellos", pero me preguntaba si todos ustedes tendrían alguna experiencia en el mundo real que les gustaría compartir eso iluminaría el tema más que la opinión que acabo de mencionar.
fuente
Respuestas:
Yo diría que el programador promedio entiende perfectamente la recursividad. De hecho, si el programador ha obtenido un título en Ciencias de la Computación o Ingeniería de Software, está prácticamente garantizado. Por supuesto, hay algunos programadores muy por debajo del promedio, pero no los quieres en tu equipo.
En este caso, la distinción entre un promedio y un buen programador es saber cuándo usar la recursión y cuándo no. Y eso depende del problema que se resuelva Y del lenguaje utilizado para resolverlo.
Si está utilizando un lenguaje de programación funcional, la recursividad es una solución natural y eficiente para una amplia gama de problemas. (¡Reglas de optimización de recursión de cola!)
Si está utilizando un OO o un lenguaje de procedimiento simple, la recursión puede ser ineficiente y puede ser problemática debido a desbordamientos de la pila. Entonces, en algunos casos, elegiría una solución iterativa en lugar de una recursiva. Sin embargo, en otros casos, la solución recursiva es mucho más simple y elegante que la solución iterativa (posiblemente más eficiente) sería la "demasiado inteligente". (Por ejemplo, si el problema requiere retroceder, construir o caminar árboles / gráficos, etc., la recursión es a menudo más simple).
fuente
Algunos problemas son naturalmente recursivos. Encontrar una solución iterativa en estos casos en realidad puede ser más torpe y complejo que los recursivos. Un buen ejemplo es cualquier algoritmo que necesite atravesar una estructura de árbol jerárquica, que es una tarea común en la programación.
TL; versión DR: No.
fuente
La recursión es un principio fundamental en la mayoría de los lenguajes de programación funcionales. La iteración (bucle) en lenguajes funcionales generalmente se logra a través de la recursividad.
Los lenguajes funcionales han visto un renacimiento últimamente, debido a la necesidad de manejar con elegancia más núcleos de procesador; los lenguajes funcionales ayudan a lograr este tipo de concurrencia al proporcionar formas de razonar mejor sobre su programa sin la complejidad que implica bloquear estructuras mutables.
fuente
Algunos problemas, como caminar por la estructura de un árbol (caminar, por ejemplo, una estructura de directorio completa, en lugar de, por ejemplo, buscar un nodo B-Tree específico), son ideales para usar la recursividad; los equivalentes no recursivos a menudo simplemente agregan la complicación de administrar su propia pila.
En estos casos, la recursión es la mejor solución, la más simple y la más fácil de entender.
fuente
Yo diría que use la recursividad donde sea apropiado, pero siempre busque formas de evitar la recursividad explícita.
Por ejemplo, si encuentra la necesidad de atravesar manualmente una estructura de árbol, entonces sí, debería usar la recursividad. Si alguien es lo suficientemente tonto como para no entender un recorrido recursivo del árbol, no harán ni la cabeza ni la cola de la versión iterativa.
Pero una mejor opción es usar un iterador que abstraiga la recursión hasta el punto en que todo lo que ve es "Realizo esta operación en todo el árbol".
fuente
La recursividad es el mecanismo más simple desde el punto de vista de la limpieza del código. Si la velocidad es absolutamente esencial, entonces quizás pueda usar una matriz 2D de parámetros problemáticos. Engendrar un proceso hijo es simplemente agregar otro elemento a la matriz. Una vez hice un solucionador tridiagonal de ensamblador, eso fue un gran problema en el pasado. El contexto necesario por instancia era de 8 palabras por nivel, y cada subproblema era un tercio del tamaño del anterior. Esta "biblioteca" solo era popular porque superaba a todas las demás implementaciones. Pero, esa es una situación bastante rara en la programación, por lo que no necesita sucumbir a la "optimización prematura", simplemente porque esta solución está disponible. Obviamente, por algunas cosas, es una exageración terrible, como el ejemplo de recursión 101 "calcular el factorial". Pero para la mayoría de las aplicaciones,
Tengo un simple corrector ortográfico que uso para una aplicación (donde quiero dar pistas sobre cómo corregir errores ortográficos menores), donde calculo la "distancia" entre dos cadenas, permitiendo que se permitan eliminaciones y adiciones. Esto conduce a una estructura de árbol potencialmente grande, y las ramas se recortan ya que solo nos preocupamos por las coincidencias cercanas. Con la recursividad, son quizás veinte líneas de código (tengo las versiones Fortran y C). Creo que sería desordenado de lo contrario. ¡Diablos, fue mucho más fácil programar / depurar la verificación que pensar en ese árbol!
fuente
Lo entiendo pero nunca lo he usado explícitamente. Creo que cualquiera que se llame a sí mismo programador debe saber o aprender lo que es tanto como necesita saber qué son la pila y el montón. Hola, todo el mundo necesita saber cómo funciona min / max en tic-tac-toe, a través de una recurrencia elegante.
fuente