Διαδρομές
/
Elixir
Elixir
/
Ασκήσεις
/
Αριθμομηχανή RPN
Αριθμομηχανή RPN

Αριθμομηχανή RPN

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

Εισαγωγή

Σφάλματα

Τα σφάλματα συμβαίνουν. Στην Elixir, ενώ οι άνθρωποι συχνά λένε "άφησέ το να κρασάρει", υπάρχουν στιγμές που χρειάζεται να διασώσουμε την κλήση της συνάρτησης σε μια γνωστή καλή κατάσταση για να εκπληρώσουμε ένα συμβόλαιο λογισμικού. Σε ορισμένες γλώσσες προγραμματισμού, τα σφάλματα χρησιμοποιούνται ως μέθοδος ροής ελέγχου, αλλά στην Elixir αυτό το μοτίβο αποθαρρύνεται. Συχνά μπορούμε να αναγνωρίσουμε συναρτήσεις που μπορεί να πετάξουν ένα σφάλμα μόνο από το όνομά τους: οι συναρτήσεις που πετούν σφάλματα έχουν ! στο τέλος του ονόματός τους. Αυτό συμβαίνει σε αντιδιαστολή με συναρτήσεις που επιστρέφουν {:ok, value} ή :error. Δες αυτά τα παραδείγματα από τη βιβλιοθήκη:

Map.fetch(%{a: 1}, :b)
# => :error
Map.fetch!(%{a: 1}, :b)
# => raises KeyError

Try/Rescue

Η Elixir παρέχει έναν μηχανισμό για να διασώζεσαι από σφάλματα χρησιμοποιώντας try .. rescue

try do
  raise RuntimeError, "error"
rescue
  e in RuntimeError -> :error
end

Ας εξετάσουμε αυτόν τον μηχανισμό:

  • Γραμμή 1, το μπλοκ δηλώνεται με try.
  • Γραμμή 2, εδώ τοποθετείται η κλήση της συνάρτησης που μπορεί να πετάξει σφάλμα, στην περίπτωση αυτή καλούμε τη raise/2.
  • Γραμμή 4, στο τμήμα rescue, κάνουμε αντιστοίχιση προτύπων στο όνομα του Module του σφάλματος που πετάχτηκε
    • στην αριστερή πλευρά του ->:
      • το e αντιστοιχίζεται στο struct του σφάλματος.
      • το in είναι λέξη-κλειδί.
      • το RuntimeError είναι το σφάλμα από το οποίο θέλουμε να διασωθούμε.
        • Αν θέλαμε να διασωθούμε από όλα τα σφάλματα, θα μπορούσαμε να χρησιμοποιήσουμε _ αντί για το όνομα του module ή να παραλείψουμε εντελώς τη λέξη-κλειδί in.
    • στη δεξιά πλευρά:
      • οι εντολές που θα εκτελεστούν αν το σφάλμα ταιριάξει.

Structs σφάλματος

Τα σφάλματα (που μερικές φορές αποκαλούνται και "εξαιρέσεις") από τα οποία διασώζεσαι με αυτόν τον τρόπο είναι structs. Η διάσωση από σφάλματα στην Elixir γίνεται πολύ σπάνια. Συνήθως το σφάλμα από το οποίο διασωθήκαμε καταγράφεται ή στέλνεται σε μια εξωτερική υπηρεσία παρακολούθησης και μετά πετιέται ξανά. Αυτό σημαίνει ότι συνήθως δε μας ενδιαφέρει η εσωτερική δομή του συγκεκριμένου struct σφάλματος.

Στην έννοια Exceptions θα μάθεις περισσότερα για τα structs σφάλματος, συμπεριλαμβανομένου του πώς να ορίσεις το δικό σου προσαρμοσμένο σφάλμα.

Οδηγίες

Ενώ εργάζεσαι στην Instruments of Texas, σου έχει ανατεθεί να δουλέψεις πάνω σε μια πειραματική αριθμομηχανή Αντίστροφης Πολωνικής Σημειογραφίας [RPN] γραμμένη σε Elixir. Η ομάδα σου αντιμετωπίζει ένα πρόβλημα: κάποιες πράξεις πετούν σφάλματα και κάνουν τη διαδικασία να καταρρεύσει. Σου έχει ανατεθεί να γράψεις μια συνάρτηση που περιτυλίγει τη συνάρτηση πράξης, ώστε τα σφάλματα να μπορούν να αντιμετωπιστούν πιο κομψά με ιδιωματικό κώδικα Elixir.

1. Προειδοποίησε την ομάδα

Υλοποίησε τη συνάρτηση calculate!/2 ώστε να καλεί τη συνάρτηση πράξης με τη στοίβα ως μοναδικό όρισμα. Η συνάρτηση πράξης ορίζεται κάπου αλλού, αλλά ξέρεις ότι μπορεί είτε να ολοκληρωθεί με επιτυχία είτε να πετάξει ένα σφάλμα.

stack = []
operation = fn _ -> :ok end
RPNCalculator.calculate!(stack, operation)
# => :ok

stack = []
operation = fn _ -> raise ArgumentError, "An error occurred" end
RPNCalculator.calculate!(stack, operation)
# => ** (ArgumentError) An error occurred

Τα ονόματα συναρτήσεων που τελειώνουν σε ! προειδοποιούν τους προγραμματιστές ότι αυτή η συνάρτηση μπορεί να πετάξει ένα σφάλμα

2. Περιτύλιξε το σφάλμα

Όταν κάνεις περισσότερη έρευνα, παρατηρείς ότι πολλές συναρτήσεις χρησιμοποιούν άτομα και πλειάδες για να δηλώσουν την επιτυχία ή την αποτυχία τους. Υλοποίησε τη calculate/2 χρησιμοποιώντας αυτή τη στρατηγική.

stack = []
operation = fn _ -> "operation completed" end
RPNCalculator.calculate(stack, operation)
# => {:ok, "operation completed"}

stack = []
operation = fn _ -> raise ArgumentError, "An error occurred" end
RPNCalculator.calculate(stack, operation)
# => :error

3. Μεταβίβασε το μήνυμα

Κάποια από τα σφάλματα περιέχουν σημαντικές πληροφορίες που οι συνάδελφοί σου πρέπει να έχουν για να διασφαλίσουν τη σωστή λειτουργία του συστήματος. Υλοποίησε τη calculate_verbose/2 για να μεταβιβάσεις το μήνυμα του σφάλματος. Το σφάλμα είναι ένα struct που έχει ένα πεδίο :message.

stack = []
operation = fn _ -> "operation completed" end
RPNCalculator.calculate_verbose(stack, operation)
# => {:ok, "operation completed"}

stack = []
operation = fn _ -> raise ArgumentError, "An error occurred" end
RPNCalculator.calculate_verbose(stack, operation)
# => {:error, "An error occurred"}
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Elixir Exercism

Έτοιμος να ξεκινήσεις την άσκηση Αριθμομηχανή RPN;

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