Tracks
/
Elixir
Elixir
/
Übungen
/
Stack Underflow
Stack Underflow

Stack Underflow

Lernübung

Einführung

Ausnahmen

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:

  • Der Name des Moduls legt den Namen des Fehlers fest.
  • Das Modul definiert ein Fehler-Struct.
  • Das Struct hat ein :message-Feld.
  • Das Modul kann mit 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.

Eine Ausnahme definieren

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

Ausnahmen verwenden

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.

Anleitung

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.

1. Fehler bei Division durch null

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

2. Fehler bei einem Stack-Underflow

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

3. Schreibe eine Funktion zum Dividieren

Implementiere die Funktion divide/1, die einen Stack (eine Liste mit zwei Zahlen) entgegennimmt und:

  • Stack-Underflow auslöst, wenn der Stack nicht genug Zahlen enthält
  • Division durch null auslöst, wenn der Divisor 0 ist (beachte, der Stack mit den Zahlen ist in umgekehrter Reihenfolge gespeichert)
  • die Division ausführt, wenn keine Fehler ausgelöst werden
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!

Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
Elixir Exercism

Bereit, mit Stack Underflow zu starten?

Melde dich bei Exercism an, um Elixir mit 58 Konzepte168 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.