Todos os erros em Elixir implementam o comportamento Exception. Tal como o comportamento Access, o comportamento Exception define funções de callback que um módulo tem de implementar para cumprir o contrato de software do comportamento. Assim que um erro é definido, tem as seguintes propriedades:
:message.raise/1 e raise/2 para lançar o erro pretendidoO comportamento Exception também especifica dois callbacks: message/1 e exception/1. Se não forem implementadas, serão usadas implementações predefinidas. message/1 transforma a estrutura de erro numa mensagem legível quando é chamada com raise. exception/1 permite adicionar contexto adicional à mensagem quando é chamada com raise/2
Para definir uma exceção a partir de um módulo de erro, usamos a macro defexception:
# Defines a minimal error, with the name `MyError`
defmodule MyError do
defexception message: "error"
end
# Defines an error with a customized exception/1 function
defmodule MyCustomizedError do
defexception message: "custom error"
@impl true
def exception(value) do
case value do
[] ->
%MyCustomizedError{}
_ ->
%MyCustomizedError{message: "Alert: " <> value}
end
end
end
Os erros definidos podem ser usados como um erro incorporado, utilizando raise/1 ou raise/2.
raise/1 lança um erro específico pelo nome do módulo ou, se o argumento for uma string, lança um RuntimeError com a string como mensagem.raise/2 lança um erro específico pelo nome do módulo e aceita um argumento de atributos que é usado para obter o erro com a mensagem apropriada.Enquanto continuas o teu trabalho na Instruments of Texas, estão a ser feitos progressos na implementação em Elixir da calculadora RPN. A tua equipa gostaria de poder lançar erros mais específicos do que os erros genéricos fornecidos pela biblioteca padrão. Estás a fazer alguma investigação, mas decidiste implementar dois novos erros que implementam o Exception Behaviour.
Dividir um número por zero produz um resultado indefinido, que a equipa decide ser melhor representado por um erro.
Implementa o módulo DivisionByZeroError com a mensagem de erro: "division by zero occurred"
raise DivisionByZeroError
# => ** (DivisionByZeroError) division by zero occurred
As calculadoras RPN usam uma pilha para acompanhar os números antes de serem adicionados. A equipa representa esta pilha com uma lista de números (inteiros e de vírgula flutuante), por exemplo: [3, 4.0]. Cada operação precisa de um número específico de números na pilha para realizar o seu cálculo. Quando não há números suficientes na pilha, isto chama-se um erro de underflow da pilha. Implementa a exceção StackUnderflowError, que fornece uma mensagem predefinida e contexto extra opcional.
raise StackUnderflowError
# => ** (StackUnderflowError) stack underflow occurred
raise StackUnderflowError, "when dividing"
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing
Implementa a função divide/1, que recebe uma pilha (uma lista de dois números) e:
RPNCalculator.Exception.divide([])
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing
RPNCalculator.Exception.divide([0, 100])
# => ** (DivisionByZeroError) division by zero occurred
RPNCalculator.Exception.divide([4, 16])
# => 4
Repara que a ordem da lista está invertida!
Inscreve-te no Exercism para aprenderes e dominares Elixir com 58 conceitos168 exercícios, e mentoria humana real, tudo grátis.