Track
/
Elixir
Elixir
/
Esercizi
/
Underflow dello stack
Underflow dello stack

Underflow dello stack

Esercizio di apprendimento

Introduzione

Eccezioni

Tutti gli errori in Elixir implementano l'Exception Behaviour. Proprio come l'Access Behaviour, l'Exception Behaviour definisce delle funzioni di callback che un modulo deve implementare per rispettare il contratto software del behaviour. Una volta che un errore è definito, ha le seguenti proprietà:

  • Il nome del modulo definisce il nome dell'errore.
  • Il modulo definisce una struct di errore.
  • La struct avrà un campo :message.
  • Il modulo può essere usato con raise/1 e raise/2 per sollevare l'errore desiderato.

L'Exception Behaviour specifica anche due callback: message/1 e exception/1. Se non vengono implementate, verranno usate le implementazioni predefinite. message/1 trasforma la struct di errore in un messaggio leggibile quando viene chiamata con raise. exception/1 permette di aggiungere contesto al messaggio quando viene chiamata con raise/2.

Definire un'eccezione

Per definire un'eccezione a partire da un modulo di errore, usiamo 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

Usare le eccezioni

Gli errori definiti possono essere usati come un errore integrato, usando raise/1 o raise/2.

  • raise/1 solleva un errore specifico tramite il nome del suo modulo oppure, se l'argomento è una stringa, solleva un RuntimeError con la stringa come messaggio.
  • raise/2 solleva un errore specifico tramite il nome del suo modulo e accetta un argomento di attributi che viene usato per ottenere l'errore con il messaggio appropriato.

Istruzioni

Mentre continui a lavorare presso Instruments of Texas, si stanno facendo progressi sull'implementazione in Elixir della calcolatrice RPN. Il tuo team vorrebbe poter sollevare errori più specifici di quelli generici forniti dalla libreria standard. Stai facendo qualche ricerca, ma hai deciso di implementare due nuovi errori che seguono l'Exception Behaviour.

1. Errore per la divisione per zero

Dividere un numero per zero produce un risultato indefinito: il team ha deciso che è meglio rappresentarlo con un errore.

Implementa il modulo DivisionByZeroError in modo che abbia il messaggio di errore: "division by zero occurred"

raise DivisionByZeroError
# => ** (DivisionByZeroError) division by zero occurred

2. Errore quando si verifica uno stack underflow

Le calcolatrici RPN usano uno stack per tenere traccia dei numeri prima che vengano utilizzati nei calcoli. Il team rappresenta questo stack con un array di numeri (interi e in virgola mobile), ad esempio: [3, 4.0]. Ogni operazione richiede una quantità precisa di numeri sullo stack per poter eseguire il proprio calcolo. Quando sullo stack non ci sono abbastanza numeri, si parla di errore di stack underflow. Implementa l'eccezione StackUnderflowError, che fornisce un messaggio predefinito e un contesto aggiuntivo opzionale

raise StackUnderflowError
# => ** (StackUnderflowError) stack underflow occurred

raise StackUnderflowError, "when dividing"
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing

3. Scrivi una funzione di divisione

Implementa la funzione divide/1, che prende uno stack (un array di due numeri) e:

  • solleva stack underflow quando lo stack non contiene abbastanza numeri
  • solleva division by zero quando il divisore è 0 (nota che lo stack di numeri è memorizzato in ordine inverso)
  • esegue la divisione quando non viene sollevato alcun errore
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

Nota che l'ordine dell'array è invertito!

Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Elixir Exercism

Vuoi iniziare Underflow dello stack?

Iscriviti a Exercism per imparare e padroneggiare Elixir con 58 concetti168 esercizi e il mentoring di persone reali, tutto gratis.