Buscar..


Usos básicos de las cláusulas de guardia.

En Elixir, se pueden crear múltiples implementaciones de una función con el mismo nombre y especificar reglas que se aplicarán a los parámetros de la función antes de llamar a la función para determinar qué implementación ejecutar.

Estas reglas están marcadas por la palabra clave when , y van entre def function_name(params) y do en la definición de la función. Un ejemplo trivial:

defmodule Math do

  def is_even(num) when num === 1 do
    false
  end
  def is_even(num) when num === 2 do
    true
  end

  def is_odd(num) when num === 1 do
    true
  end
  def is_odd(num) when num === 2 do
    false
  end

end

Digamos que ejecuto Math.is_even(2) con este ejemplo. Hay dos implementaciones de is_even , con diferentes cláusulas de protección. El sistema los examinará en orden y ejecutará la primera implementación donde los parámetros satisfacen la cláusula de protección. El primero especifica que num === 1 que no es verdadero, por lo que pasa al siguiente. El segundo especifica que num === 2 , que es verdadero, por lo que esta es la implementación que se usa, y el valor de retorno será true .

¿Qué pasa si ejecuto Math.is_odd(1) ? El sistema analiza la primera implementación y ve que, dado que num es 1 se cumple la cláusula de protección de la primera implementación. Luego usará esa implementación y devolverá la true , y no se molestará en mirar cualquier otra implementación.

Los guardias están limitados en los tipos de operaciones que pueden ejecutar. La documentación de Elixir enumera todas las operaciones permitidas ; en pocas palabras, permiten comparaciones, operaciones matemáticas, operaciones binarias, verificación de tipos (por ejemplo, is_atom ) y un puñado de pequeñas funciones de conveniencia (por ejemplo, length ). Es posible definir cláusulas de protección personalizadas, pero requiere la creación de macros y es mejor dejarlas para una guía más avanzada.


Tenga en cuenta que los guardias no lanzan errores; se tratan como fallas normales de la cláusula de protección, y el sistema avanza para ver la siguiente implementación. Si descubre que no está (FunctionClauseError) no function clause matching al llamar a una función protegida con los parámetros que espera que funcionen, es posible que una cláusula de protección con la que espera trabajar genere un error que se está tragando.

Para ver esto por ti mismo, crea y luego llama a una función con un guardia que no tiene sentido, como este, que trata de dividir por cero:

defmodule BadMath do
  def divide(a) when a / 0 === :foo do
    :bar
  end
end

Llamar a BadMath.divide("anything") proporcionará el error algo inútil (FunctionClauseError) no function clause matching in BadMath.divide/1 - mientras que si hubiera intentado ejecutar "anything" / 0 directamente, obtendría una más útil error: (ArithmeticError) bad argument in arithmetic expression .



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow