Toutes les erreurs en Elixir implémentent le Exception Behaviour. Tout comme le Access Behaviour, le Exception Behaviour définit des fonctions de rappel qu'un module doit implémenter pour remplir le contrat logiciel du behaviour. Une fois une erreur définie, elle possède les propriétés suivantes :
:message.raise/1 et raise/2 pour lever l'erreur voulueLe Exception Behaviour définit aussi deux fonctions de rappel : message/1 et exception/1. Si elles ne sont pas implémentées, des implémentations par défaut seront utilisées. message/1 transforme la struct d'erreur en un message lisible lorsqu'elle est appelée avec raise. exception/1 permet d'ajouter du contexte supplémentaire au message lorsqu'elle est appelée avec raise/2
Pour définir une exception à partir d'un module d'erreur, on utilise la 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
Une erreur définie peut s'utiliser comme une erreur native, avec raise/1 ou raise/2.
raise/1 lève une erreur précise par le nom de son module ou, si l'argument est une string, lève une RuntimeError avec cette string comme message.raise/2 lève une erreur précise par le nom de son module et accepte un argument d'attributs qui sert à obtenir l'erreur avec le message approprié.Alors que tu poursuis ton travail chez Instruments of Texas, des progrès sont en cours sur l'implémentation en Elixir de la calculatrice RPN. Ton équipe aimerait pouvoir lever des erreurs plus spécifiques que les erreurs génériques fournies par la bibliothèque standard. Tu fais quelques recherches, mais tu as décidé de créer deux nouvelles erreurs qui implémentent le comportement Exception.
Diviser un nombre par zéro produit un résultat indéfini, que l'équipe décide de représenter au mieux par une erreur.
Implémente le module DivisionByZeroError avec le message d'erreur : "division by zero occurred"
raise DivisionByZeroError
# => ** (DivisionByZeroError) division by zero occurred
Les calculatrices RPN utilisent une stack pour garder la trace des nombres avant de les additionner. L'équipe représente cette stack par une liste de nombres (entiers et à virgule flottante), par exemple : [3, 4.0]. Chaque opération prend un nombre précis de valeurs sur la pile pour effectuer son calcul. Quand il n'y a pas assez de nombres sur la pile, on parle d'une erreur de stack underflow. Implémente l'exception StackUnderflowError, qui fournit un message par défaut ainsi qu'un contexte supplémentaire facultatif
raise StackUnderflowError
# => ** (StackUnderflowError) stack underflow occurred
raise StackUnderflowError, "when dividing"
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing
Implémente la fonction divide/1 qui prend une pile (une liste de deux nombres) et :
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
Attention, l'ordre de la liste est inversé !
Inscris-toi sur Exercism pour apprendre et maîtriser Elixir avec 58 concepts168 exercices, et un vrai mentorat humain, le tout gratuitement.