En programación informática , una condición de guarda es una expresión booleana que debe evaluarse como verdadera para que la ejecución del programa continúe en la rama en cuestión. Independientemente del lenguaje de programación utilizado, una cláusula de guarda , un código de guarda o una instrucción de guarda es una comprobación de las precondiciones de integridad que se utiliza para evitar errores durante la ejecución.
La cláusula de protección es un patrón de diseño de software atribuido a Kent Beck, quien codificó muchas prácticas de codificación, a menudo sin nombre, en patrones de diseño de software con nombre. El uso de esta técnica se remonta al menos a principios de la década de 1960. La cláusula de protección se suele añadir al principio de un procedimiento y se dice que "protege" el resto del procedimiento al gestionar los casos límite de antemano.
Usos
Un ejemplo típico es comprobar que una referencia que está a punto de ser procesada no sea nula, lo que evita fallos de puntero nulo .
Otros usos incluyen el uso de un campo booleano para la idempotencia (de modo que las llamadas subsiguientes sean nops ), como en el patrón dispose .
public String foo ( String username ) { if ( username == null ) { throw new IllegalArgumentException ( "El nombre de usuario es nulo." ); }// El resto del código del método sigue aquí... }Código más plano con menos anidamiento.
El guard proporciona una salida temprana de una subrutina y es una desviación comúnmente utilizada de la programación estructurada , eliminando un nivel de anidamiento y dando como resultado un código más plano: [ 1 ] reemplazando if guard { ... }con if not guard: return; ....
El uso de cláusulas de guarda puede ser una técnica de refactorización para mejorar el código. En general, un menor anidamiento es beneficioso, ya que simplifica el código y reduce la carga cognitiva.
Por ejemplo, en Python :
from typing import Any , Optional# Esta función no tiene cláusula de guarda def f_noguard ( x : Any ) -> Optional [ int ] if isinstance ( x , int ): # código aquí return x + 1 else : return None# Función equivalente con una cláusula de guarda. Nótese que la mayor parte del código tiene menos sangría, lo que facilita su lectura y comprensión. def f_guard ( x : Any ) -> Optional [ int ] if not isinstance ( x , int ): return None # código aquí return x + 1Otro ejemplo, escrito en C :
// Esta función no tiene cláusula de guarda int funcNoGuard ( int x ) { if ( x >= 0 ) { // código aquí return x + 1 ; } else { return 0 ; } }// Función equivalente con una cláusula de guarda int funcGuard ( int x ) { if ( x < 0 ) { return 0 ; }// código aquí return x + 1 ; }Terminología
El término se usa con un significado específico en los lenguajes de programación APL , Haskell , Clean , Erlang , occam , Promela , OCaml , Swift , [ 2 ] Python desde la versión 3.10 y Scala . En Mathematica , las guardas se llaman restricciones . Las guardas son el concepto fundamental en Guarded Command Language , un lenguaje en métodos formales . Las guardas se pueden usar para aumentar la coincidencia de patrones con la posibilidad de omitir un patrón incluso si la estructura coincide. Las expresiones booleanas en sentencias condicionales generalmente también se ajustan a esta definición de una guarda, aunque se llaman condiciones .
Matemáticas
En el siguiente ejemplo de Haskell, las guardas aparecen entre cada par de "|" y "=":
f x | x > 0 = 1 | en otro caso = 0Esto es similar a la notación matemática correspondiente:
En este caso, las condiciones se encuentran en las cláusulas "si" y "de lo contrario".
Varios guardias
Si existen varias condiciones de guarda paralelas, normalmente se prueban de arriba abajo y se elige la rama de la primera que pasa. Las condiciones de guarda en una lista de casos suelen ser paralelas.
Sin embargo, en las comprensiones de listas de Haskell , las condiciones se presentan en serie, y si alguna falla, el elemento de la lista no se genera. Esto sería equivalente a combinar las condiciones por separado con el operador lógico AND , con la salvedad de que puede haber otras cláusulas de comprensión de listas entre las condiciones.
Evolución
Una expresión condicional simple, ya presente en CPL en 1963, tiene una condición en la primera subexpresión y otra subexpresión para usar en caso de que la primera no pueda usarse. Algunas formas comunes de escribir esto:
(x>0) -> 1/x; 0 x>0 ? 1/x : 0
Si la segunda subexpresión puede ser otra expresión condicional simple, podemos ofrecer más alternativas para probar antes de la última opción :
(x>0) -> 1/x; (x<0) -> -1/x; 0
En 1966, ISWIM tenía una forma de expresión condicional sin un caso de ejecución obligatoria, separando así la condición de guarda del concepto de elegir entre dos opciones. En el caso de ISWIM, si ninguna de las alternativas podía utilizarse, el valor era indefinido , lo que significaba que nunca se computaría en un valor.
KRC , una "versión miniaturizada" [ 3 ] de SASL (1976), fue uno de los primeros lenguajes de programación en utilizar el término "guard". Sus definiciones de funciones podían tener varias cláusulas, y la que se aplicara se elegía en función de las guardas que seguían a cada cláusula:
fac n = 1 , n = 0 = n * fac ( n - 1 ), n > 0El uso de cláusulas de guarda, y el término "cláusula de guarda", se remonta al menos a la práctica de Smalltalk en la década de 1990, tal como la codificó Kent Beck . [ 1 ]
En 1996, Dyalog APL adoptó un estilo funcional puro alternativo en el que la guarda es la única estructura de control. [ 4 ] Este ejemplo, en APL, calcula la paridad del número de entrada:
paridad ← { 2 ∣ ⍵ : 'impar' 'par' }Patrón de protección
Además de una condición de guarda asociada a un patrón, la condición de guarda de patrón puede referirse al uso de la coincidencia de patrones en el contexto de una condición de guarda. En efecto, una coincidencia del patrón se interpreta como un pase. Este significado fue introducido en una propuesta para Haskell por Simon Peyton Jones titulada " Una nueva perspectiva de las condiciones de guarda" en abril de 1997 y se utilizó en la implementación de dicha propuesta. Esta característica permite utilizar patrones en las condiciones de guarda de un patrón.
Un ejemplo en Haskell extendido:
clunky env var1 var2 | Just val1 <- lookup env var1 , Just val2 <- lookup env var2 = val1 + val2 -- ...otras ecuaciones para clunky...Esto se leería: "Engorroso para un entorno y dos variables, en caso de que las búsquedas de las variables del entorno produzcan valores , es la suma de los valores..." Al igual que en las comprensiones de listas , las condiciones están en serie, y si alguna de ellas falla, la rama no se toma.
Véase también
- Afirmación
- Guarded Command Language , un lenguaje de programación basado en condicionales no deterministas.
- Suspensión vigilada
- Soporte de Iverson
- Condicional lógico
- Sentencia switch
Referencias
- 1 2 Beck, Kent (1997). "Cláusula de protección". Patrones de mejores prácticas de Smalltalk, pp. 178–179 .
- ↑ Cook, Nate. "guardar y diferir" . NSHipster . Consultado el 26 de febrero de 2016 .
- ↑ Turner, DA "Algunos antecedentes de los lenguajes de programación funcional" (PDF) .
- ↑ Scholes, John. "Funciones directas en Dyalog APL" (PDF) .
Enlaces externos
- Guard en el Diccionario en línea gratuito de informática - FOLDOC , Denis Howe (editor).
- Cláusula de protección , WikiWikiWeb
- El Informe Haskell 98 , capítulo 3 Expresiones .
- El libro de Mathematica, sección 2.3.5: Imponiendo restricciones a los patrones.
- Guía del usuario del sistema de compilación Haskell Glorious Glasgow , versión 6.4, sección 7.3.2. Guardas de patrón
- Construcciones condicionales
- Terminología de métodos formales