Trilhas
/
Elixir
Elixir
/
Programa
/
Try/Rescue
Tr

Try/Rescue em Elixir

1 exercício

Sobre Try/Rescue

Você pode usar try .. rescue para capturar e avaliar erros lançados dentro de um bloco.

Por exemplo:

try do
  raise RuntimeError, "error"
rescue
  e in RuntimeError -> :error
end
  • Linha 1, o bloco é declarado com try.
  • Linha 2, aqui fica a chamada de função que pode gerar um erro; neste caso, estamos chamando raise/1.
  • Linha 4, na seção rescue, fazemos uma correspondência de padrões com o nome do Módulo do erro lançado
    • do lado esquerdo de ->:
      • e corresponde ao struct de erro.
      • in é uma palavra-chave.
      • RuntimeError é o módulo que queremos corresponder, mas dá para corresponder com qualquer módulo de erro, ou usar _ para todos os erros.
    • do lado direito:
      • as instruções que serão executadas se o erro corresponder.

Structs de erro

Os erros que você captura desse jeito (às vezes também chamados de "exceções") são structs. Structs de erro diferentes têm chaves diferentes. Na seção "exceptions" da biblioteca padrão, você encontra uma lista de todos os erros 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}

Capturar erros em Elixir é algo muito raro. Normalmente, o erro capturado é registrado em um log ou enviado para um serviço externo de monitoramento, e depois lançado novamente. Isso significa que normalmente não nos importamos com a estrutura interna do struct de erro específico.

O conceito de exceções descreve como definir structs de erro personalizados.

Evite anti-padrões

  • Evite padrões de programação que usam erros para controlar o fluxo lógico. Isso é um anti-padrão em 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
    

Lançar ou não lançar, eis a questão

Como está escrito no guia de primeiros passos do Elixir:

Cabe à sua aplicação decidir se um erro ao [executar uma ação] é excepcional ou não. É por isso que o Elixir não impõe exceções às [...] funções. Em vez disso, deixa a cargo do desenvolvedor escolher a melhor forma de prosseguir.

Editar via GitHub O link abre em uma nova janela ou aba

Aprenda Try/Rescue