Tracks
/
Elixir
Elixir
/
Temario
/
Try/Rescue
Tr

Try/Rescue en Elixir

1 ejercicio

Acerca de Try/Rescue

try .. rescue se puede usar para capturar y evaluar los errores que se lanzan dentro de un bloque.

Por ejemplo:

try do
  raise RuntimeError, "error"
rescue
  e in RuntimeError -> :error
end
  • Línea 1: el bloque se declara con try.
  • Línea 2: aquí se coloca la llamada a la función que puede generar un error; en este caso, estamos llamando a raise/1.
  • Línea 4: en la sección rescue, hacemos coincidencia de patrones sobre el nombre del módulo del error lanzado
    • en el lado izquierdo de ->:
      • e coincide con el struct de error.
      • in es una palabra clave.
      • RuntimeError es el módulo que debe coincidir, pero puede coincidir con cualquier módulo de error, o _ con todos los errores.
    • en el lado derecho:
      • las instrucciones que se ejecutan si el error coincide.

Structs de error

Los errores (a veces también llamados «excepciones») que rescatas de esta forma son structs. Los distintos structs de error tienen distintas claves. En la sección «excepciones» de la biblioteca estándar puedes encontrar una lista de todos los errores predefinidos.

# ArithmeticError caused by division by zero
%ArithmeticError{message: "bad argument in arithmetic expression"}

# Protocol.UndefinedError caused by passing `nil` to `Enum.count/1`
%Protocol.UndefinedError{description: "", protocol: Enumerable, value: nil}

Rescatar errores en Elixir es algo que se hace muy rara vez. Normalmente, el error rescatado se registra o se envía a un servicio externo de monitorización, y después se vuelve a lanzar. Esto significa que normalmente no nos importa la estructura interna del struct de error concreto.

El concepto de excepciones describe cómo definir structs de error personalizados.

Evita los antipatrones

  • Evita los patrones de programación que usan errores para controlar el flujo lógico. Esto es un antipatrón en Elixir.

    # Avoid using errors for control-flow.
    try do
      {:ok, value} = MyModule.janky_function()
      "All good! #{value}."
    rescue
      e in RuntimeError ->
        reason = e.message
        "Uh oh! #{reason}."
    end
    
    # Rather, use control-flow structures for control-flow.
    case MyModule.janky_function() do
      {:ok, value} -> "All good! #{value}."
      {:error, reason} -> "Uh oh! #{reason}."
    end
    

Lanzar o no lanzar, esa es la cuestión

Como se explica en la guía de introducción de Elixir:

Tu aplicación decide si un error al [realizar una acción] es excepcional o no. Por eso Elixir no impone excepciones a las funciones [...]. En su lugar, deja en manos del desarrollador elegir la mejor forma de proceder.

Editar en GitHub El enlace se abre en una nueva ventana o pestaña

Aprende Try/Rescue