Alle Fehler in Elixir implementieren das Exception Behaviour. Genau wie das Access Behaviour definiert das Exception Behaviour Callback-Funktionen, die ein Modul implementieren muss, um den Software-Vertrag des Behaviours zu erfüllen. Sobald ein Fehler definiert ist, hat er die folgenden Eigenschaften:
:message-Feld.raise/1 und raise/2 verwendet werden, um den beabsichtigten Fehler auszulösen.Das Exception Behaviour legt außerdem zwei Callbacks fest: message/1 und exception/1. Wenn sie nicht implementiert sind, werden Standardimplementierungen verwendet. message/1 wandelt das Fehler-Struct in eine lesbare Nachricht um, wenn es mit raise aufgerufen wird. exception/1 ermöglicht es, der Nachricht zusätzlichen Kontext hinzuzufügen, wenn es mit raise/2 aufgerufen wird.
Um eine Ausnahme als Fehlermodul zu definieren, verwenden wir das defexception-Makro:
# 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
Definierte Fehler können wie ein eingebauter Fehler verwendet werden, und zwar mit raise/1 oder raise/2.
raise/1 löst einen bestimmten Fehler über seinen Modulnamen aus. Ist das Argument ein String, wird ein RuntimeError mit dem String als Nachricht ausgelöst.raise/2 löst einen bestimmten Fehler über seinen Modulnamen aus und akzeptiert ein Attributargument, mit dem der Fehler mit der passenden Nachricht ermittelt wird.Während du deine Arbeit bei Instruments of Texas fortsetzt, macht die Elixir-Implementierung des UPN-Rechners Fortschritte. Dein Team möchte Fehler auslösen können, die spezifischer sind als die generischen Fehler aus der Standardbibliothek. Du recherchierst noch, hast dich aber entschieden, zwei neue Fehler zu implementieren, die das Exception Behaviour umsetzen.
Wenn du eine Zahl durch null teilst, ist das Ergebnis undefiniert. Das Team entscheidet, dass ein Fehler das am besten darstellt.
Implementiere das Modul DivisionByZeroError mit der Fehlermeldung: "division by zero occurred"
raise DivisionByZeroError
# => ** (DivisionByZeroError) division by zero occurred
UPN-Rechner verwenden einen Stack, um Zahlen zu verwalten, bevor sie addiert werden. Das Team stellt diesen Stack als eine Liste von Zahlen dar (Ganzzahlen und Gleitkommazahlen), z. B.: [3, 4.0]. Jede Operation benötigt eine bestimmte Anzahl an Zahlen auf dem Stack, um ihre Berechnung durchzuführen. Wenn nicht genug Zahlen auf dem Stack liegen, nennt man das einen Stack-Underflow-Fehler. Implementiere die Exception StackUnderflowError, die eine Standardmeldung und einen optionalen zusätzlichen Kontext bereitstellt
raise StackUnderflowError
# => ** (StackUnderflowError) stack underflow occurred
raise StackUnderflowError, "when dividing"
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing
Implementiere die Funktion divide/1, die einen Stack (eine Liste mit zwei Zahlen) entgegennimmt und:
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
Beachte: Die Reihenfolge der Liste ist umgekehrt!
Melde dich bei Exercism an, um Elixir mit 58 Konzepte168 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.