Διαδρομές
/
Elixir
Elixir
/
Ασκήσεις
/
Υποχείλιση στοίβας
Υποχείλιση στοίβας

Υποχείλιση στοίβας

Άσκηση εκμάθησης

Εισαγωγή

Εξαιρέσεις

Όλα τα σφάλματα στην Elixir υλοποιούν τη Συμπεριφορά Exception. Ακριβώς όπως η Συμπεριφορά Access, η Συμπεριφορά Exception ορίζει συναρτήσεις callback που πρέπει να υλοποιήσει ένα module για να εκπληρώσει το συμβόλαιο λογισμικού της συμπεριφοράς. Μόλις οριστεί ένα σφάλμα, έχει τις εξής ιδιότητες:

  • Το όνομα του module ορίζει το όνομα του σφάλματος.
  • Το module ορίζει ένα struct σφάλματος.
  • Το struct θα έχει ένα πεδίο :message.
  • Το module μπορεί να χρησιμοποιηθεί με τις raise/1 και raise/2 για να πετάξει το σφάλμα που θέλεις

Η Συμπεριφορά Exception ορίζει επίσης δύο callbacks: τις message/1 και exception/1. Αν δεν υλοποιηθούν, θα χρησιμοποιηθούν προεπιλεγμένες υλοποιήσεις. Η message/1 μετατρέπει το struct σφάλματος σε ένα αναγνώσιμο μήνυμα όταν κληθεί με το raise. Η exception/1 επιτρέπει να προστεθεί επιπλέον περιβάλλον στο μήνυμα όταν κληθεί με το raise/2

Ορίζοντας μια εξαίρεση

Για να ορίσουμε μια εξαίρεση από ένα module σφάλματος, χρησιμοποιούμε το 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

Χρησιμοποιώντας εξαιρέσεις

Τα σφάλματα που έχουν οριστεί μπορούν να χρησιμοποιηθούν όπως ένα ενσωματωμένο σφάλμα, είτε με το raise/1 είτε με το raise/2.

  • Το raise/1 πετάει ένα συγκεκριμένο σφάλμα με βάση το όνομα του module του ή, αν το όρισμα είναι συμβολοσειρά, πετάει ένα RuntimeError με τη συμβολοσειρά ως μήνυμα.
  • Το raise/2 πετάει ένα συγκεκριμένο σφάλμα με βάση το όνομα του module του και δέχεται ένα όρισμα attributes, το οποίο χρησιμοποιείται για να ληφθεί το σφάλμα με το κατάλληλο μήνυμα.

Οδηγίες

Καθώς συνεχίζεις τη δουλειά σου στην Instruments of Texas, γίνεται πρόοδος στην υλοποίηση σε Elixir της αριθμομηχανής RPN. Η ομάδα σου θα ήθελε να μπορεί να πετάει σφάλματα πιο συγκεκριμένα από τα γενικά σφάλματα που παρέχει η βασική βιβλιοθήκη. Κάνεις κάποια έρευνα, αλλά έχεις αποφασίσει να υλοποιήσεις δύο νέα σφάλματα που υλοποιούν το Exception Behaviour.

1. Σφάλμα για τη διαίρεση με το μηδέν

Η διαίρεση ενός αριθμού με το μηδέν παράγει ένα απροσδιόριστο αποτέλεσμα, το οποίο η ομάδα αποφασίζει ότι αναπαρίσταται καλύτερα με ένα σφάλμα.

Υλοποίησε το άρθρωμα DivisionByZeroError ώστε να έχει το μήνυμα σφάλματος: "division by zero occurred"

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

2. Σφάλμα κατά την υποχείλιση της στοίβας

Οι αριθμομηχανές RPN χρησιμοποιούν μια στοίβα για να κρατούν τους αριθμούς πριν γίνει πάνω τους κάποια πράξη. Η ομάδα αναπαριστά αυτή τη στοίβα με μια λίστα αριθμών (ακέραιων και κινητής υποδιαστολής), π.χ.: [3, 4.0]. Κάθε πράξη χρειάζεται έναν συγκεκριμένο αριθμό αριθμών στη στοίβα για να εκτελέσει τον υπολογισμό της. Όταν δεν υπάρχουν αρκετοί αριθμοί στη στοίβα, αυτό ονομάζεται σφάλμα υποχείλισης στοίβας. Υλοποίησε την εξαίρεση StackUnderflowError που παρέχει ένα προεπιλεγμένο μήνυμα και προαιρετικό επιπλέον πλαίσιο

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

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

3. Γράψε μια συνάρτηση διαίρεσης

Υλοποίησε τη συνάρτηση divide/1 που παίρνει μια στοίβα (μια λίστα με δύο αριθμούς) και:

  • πετάει υποχείλιση στοίβας όταν η στοίβα δεν περιέχει αρκετούς αριθμούς
  • πετάει διαίρεση με το μηδέν όταν ο διαιρέτης είναι 0 (πρόσεξε ότι η στοίβα των αριθμών αποθηκεύεται σε αντίστροφη σειρά)
  • εκτελεί τη διαίρεση όταν δεν πετάγεται κανένα σφάλμα
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

Πρόσεξε ότι η σειρά της λίστας είναι αντεστραμμένη!

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Elixir Exercism

Έτοιμος να ξεκινήσεις την άσκηση Υποχείλιση στοίβας;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις Elixir με 58 έννοιες168 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.