En programación informática , una cláusula de protección es una expresión booleana que debe evaluarse como verdadera si la ejecución del programa debe continuar en la rama en cuestión. Independientemente del lenguaje de programación que se utilice, una cláusula de protección , un código de protección o una declaración de protección es una verificación de condiciones de integridad que se utiliza para evitar errores durante la ejecución.
Un ejemplo típico es verificar que una referencia que está a punto de procesarse no sea nula, lo que evita errores de puntero nulo .
Otros usos incluyen el uso de un campo booleano para idempotencia (para que las llamadas subsiguientes sean nops ), como en el patrón dispose .
public String foo ( String nombre de usuario ) { if ( nombre de usuario == null ) { throw new IllegalArgumentException ( "El nombre de usuario es nulo." ); } // El resto del código del método sigue aquí... }
La protección proporciona una salida temprana de una subrutina y es una desviación comúnmente utilizada de la programación estructurada , que elimina un nivel de anidamiento y da como resultado un código más plano: [1] reemplazando if guard { ... }
con if not guard: return; ...
.
El uso de cláusulas de protección puede ser una técnica de refactorización para mejorar el código. En general, es bueno que haya menos anidación, ya que simplifica el código y reduce la carga cognitiva.
Por ejemplo, en Python :
# Esta función no tiene cláusula de protección def f_noguard ( x ): if isinstance ( x , int ): #código #código #código return x + 1 else : return None# Función equivalente con una cláusula de protección. Tenga en cuenta que la mayor parte del código está menos sangrado, lo que facilita la lectura y el razonamiento sobre def f_guard ( x ): if not isinstance ( x , int ): return None #code #code #code return x + 1
Otro ejemplo, escrito en C :
// Esta función no tiene cláusula de protección int funcNoGuard ( int x ) { if ( x >= 0 ) { //código //código //código return x + 1 ; } else { return 0 ; } } // Función equivalente con una cláusula de protección int funcGuard ( int x ) { if ( x < 0 ) { return 0 ; } //código //código //código devuelve x + 1 ; }
El término se utiliza 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 . [ cita requerida ] En Mathematica , las protecciones se denominan restricciones . Las protecciones son el concepto fundamental en Guarded Command Language , un lenguaje de métodos formales . Las protecciones se pueden utilizar para aumentar la coincidencia de patrones con la posibilidad de omitir un patrón incluso si la estructura coincide. Las expresiones booleanas en declaraciones condicionales generalmente también se ajustan a esta definición de protección, aunque se denominan condiciones .
En el siguiente ejemplo de Haskell, las protecciones aparecen entre cada par de "|" y "=":
f x | x > 0 = 1 | en caso contrario = 0
Esto es similar a la notación matemática respectiva:
En este caso las protecciones están en las cláusulas "si" y "de lo contrario".
Si hay varios guardias paralelos, normalmente se prueban en orden de arriba hacia abajo y se elige la rama del primero que pasa. Los guardias en una lista de casos suelen ser paralelos.
Sin embargo, en las listas por comprensión de Haskell , las protecciones están en serie y, si alguna de ellas falla, el elemento de la lista no se produce. Esto sería lo mismo que combinar las protecciones separadas con AND lógico , excepto que puede haber otras cláusulas de listas por comprensión entre las protecciones.
Una expresión condicional simple, ya presente en CPL en 1963, tiene una protección en la primera subexpresión y otra subexpresión para usar en caso de que no se pueda usar la primera. Algunas formas comunes de escribir esto:
(x>0) -> 1/x; 0x>0 ? 1/x : 0
Si la segunda subexpresión puede ser otra expresión condicional simple, podemos dar más alternativas para probar antes de la última falla :
(x>0) -> 1/x; (x<0) -> -1/x; 0
En 1966, ISWIM tenía una forma de expresión condicional sin un caso de transición obligatoria, lo que separaba la protección del concepto de elegir entre una u otra. En el caso de ISWIM, si no se podía utilizar ninguna de las alternativas, el valor debía ser undefined , que estaba definido para no convertirse nunca 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 "guarda". Sus definiciones de funciones podían tener varias cláusulas, y la que se aplicaba 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 > 0
El uso de cláusulas de protección, y el término "cláusula de protección", se remonta al menos a la práctica de Smalltalk en la década de 1990, tal como lo codificó Kent Beck . [1]
En 1996, Dyalog APL adoptó un estilo funcional puro alternativo en el que la protección es la única estructura de control. [4] Este ejemplo, en APL, calcula la paridad del número de entrada:
paridad ← { 2 ∣ ⍵ : 'impar' 'par' }
Además de una protección adjunta a un patrón, la protección de patrón puede referirse al uso de coincidencia de patrones en el contexto de una protección. En efecto, una coincidencia del patrón se considera que significa pasar. Este significado fue introducido en una propuesta para Haskell por Simon Peyton Jones titulada Una nueva vista de las protecciones en abril de 1997 y se utilizó en la implementación de la propuesta. La característica proporciona la capacidad de usar patrones en las protecciones de un patrón.
Un ejemplo en Haskell extendido:
env torpe var1 var2 | Solo val1 <- búsqueda env var1 , Solo val2 <- búsqueda env var2 = val1 + val2 -- ...otras ecuaciones para torpe...
Esto se leería: "Es complicado 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...". Como en las listas por comprensión , las protecciones están en serie, y si alguna de ellas falla, no se toma la rama.