Este artículo se enfoca en discutir el problema de escaleras y escaleras elif y else if y la solución para el mismo en los lenguajes de programación C y Python.
El ELIF y ELSE IF Ladder and Stairs Problem
Hay programadores que rehúyen las secuencias largas de IF, ELSE IF, ELSE IF, ELSE IF , etc. que normalmente terminan con una cláusula ELSE final. En lenguajes con sintaxis ELSE IF o elif , el patrón se denomina «escalera ELSE IF». En lenguajes sin ELSE IF o elif , cada ELSE IF conceptual se escribe como un IF colocado dentro de la parte ELSE de su predecesor. Con sangría, parece como descender una escalera al revés.
- Esto forma una estructura de programación indeseable, difícil de leer, peor de mejorar y propensa a errores.
- Con sangría, el código de escalera cae del lado derecho de la pantalla.
- Para algunos programadores, el problema es la estética, mientras que otros se preocupan por la mantenibilidad.
- A veces, la sintaxis realmente se interpone en la forma de expresar la lógica que debe expresarse.
Fundamentalmente, este patrón expresa tanto la priorización como un cortocircuito:
- La priorización es que las declaraciones se procesan solo para el primer VERDADERO entre un conjunto de condiciones.
- El cortocircuito es que después de que se determina que la primera condición es verdadera, ni siquiera se evalúan más expresiones de condición de prueba. Esto es importante porque las expresiones de condición pueden invocar algunas funciones, como IF (42 < somefunction( x ) ). . . , donde algunas funciones pueden tener estado y tener efectos secundarios.
Cualquier alternativa debe mantener esta semántica. Además, a veces hay declaraciones que deben ejecutarse solo si fallan algunas condiciones anteriores, pero deben ejecutarse para todas las condiciones posteriores.
Ejemplo:
C
// Many people find this code // undesirable to work with. if (a < b) { // a<b statements } else if (b < c) { // b<c statements } else if (c < d) { // Statements before every // remaining possibility a = 45; // c<d statements } else if (d < e) { // Statements before every // remaining possibility a = 45; // d<e statements } else if (e < f) { // Statements before every // remaining possibility a = 45; // e<f statements } else { // Statements before every // remaining possibility a = 45; // else statements }
Python3
# Many people find this code # undesirable to work with. if (a < b): # a<b statements elif (b < c): # b<c statements elif (c < d): # statements before every # remaining possibility a = 45 # c<d statements elif (d < e): # statements before every # remaining possibility a = 45 # d<e statements elif (e < f): # statements before every # remaining possibility a = 45 # e<f statements else: # statements before every # remaining possibility a = 45 # else statements # end of IF-ELIF-ELSE pass # Contributed by David A. Kra
Tenga en cuenta que esta repetición de declaraciones que se aplican a cada una de las posibilidades posteriores ( a = 45 ) viola el principio «No se repita» (DRY). Cualquier cambio debe repetirse después de cada condición.
Enfoque de dos pasos para eliminar ELSE IF y ELSE
En lugar del código ELSE IF y ELSE anterior, el siguiente enfoque elimina la necesidad de ellos, mientras mantiene la priorización y la semántica de cortocircuito:
- Coloque un conjunto de sentencias IF independientes dentro de un ciclo de una sola iteración. No utilice ninguna sintaxis ELSE IF o ELSE .
- Agregue una declaración de salida de bucle como la última de las declaraciones dentro de cada IF . Se prefiere BREAK a CONTINUE . El código de Python ofrece una versión for y while del bucle. BREAK debe usarse con la versión while del ciclo.
Ejemplo:
C
// This is the ELSEless equivalent. do { // This is a one pass WHILE loop. if (a < b) { // a<b statements break; } if (b < c) { // b<c statements break; } // Statements for every remaining // possibility a = 45; // More conditions if (c < d) { // c<d statements break; } if (d < e) { // d<e statements break; } if (e < f) { // e<f statements break; } // else statements q = 75; // break unnecessary. // Already at end of loop. } while (0); // Once was enough. Do not repeat it.
Python3
# This is the ELSEless equivalent. # for version # !!!! Use any one and # only one value in the iteration set. !!!! # forversion="""for i in ("once - elseless"):""" # while version # !!!! requires a BREAK # at the bottom !!!! # whileversion="""while(True):""" while (True): if (a < b): # a<b statements break if (b < c): # b<c statements break # statements for every remaining # possibility indenting aligns # with the if's above a = 45 if (c < d): # c<d statements break if (d < e): # d<e statements break if (e < f): # e<f statements break # else statements # indenting aligns with the if's above q = 75 # for version: break unnecessary. # Already at end of one-pass loop. # while version: break absolutely # required for the while version break # required for the while version pass # past end of else-less IF-ELIF-ELSE # Contributed by David A. Kra
Explicación: Rara vez, o nunca, codificamos intencionalmente un ciclo que siempre se usará exactamente para una iteración, pero aquí lo hacemos. La mayoría de los lenguajes de programación proporcionan una declaración de control de bucle, como BREAK para salir de un bucle por completo, o CONTINUE , para saltar a la siguiente iteración del bucle. Sin embargo, en este uso de bucle de un solo paso, no habrá ni debe haber ninguna iteración siguiente.
Esta solución explota estas declaraciones de iteración en lugar de ELSE IF y ELSE . La instrucción BREAK o CONTINUE hace que se omitan todas las demás instrucciones dentro del bucle. Cuando el ciclo se especifica para tener solo una iteración, incluso una instrucción CONTINUAR lleva a salir del ciclo.
En el ejemplo de código, CONTINUE o BREAK funcionarán con la versión C o la versión de bucle for en python. La versión de python del ciclo while requiere el uso de la declaración break , incluida una después de las declaraciones finales equivalentes a else.
Además, entre las declaraciones IF , puede haber declaraciones adicionales que se ejecuten antes de probar cualquiera de las condiciones posteriores.
Costo de procesamiento o gastos generales: la versión de python experimenta los gastos generales mínimos de configurar el bucle. La sobrecarga en C es incluso menor, y si se usa un compilador de optimización inteligente, es posible que no haya sobrecarga en absoluto.
Resumen
A primera vista, este modismo parece un truco innecesario. Tras una consideración más cuidadosa, hace que la aplicación sea más fácil de entender y mantener. Lo usaría con lenguajes compilados, especialmente con un compilador optimizador. También lo usaría en idiomas interpretados, excepto en un punto de acceso crítico para el rendimiento. Incluso allí, lo usaría inicialmente y volvería a if, elif, elif, elif… else solo después de la depuración completa de la aplicación.