catch#
Χειρίζεται μια εξαίρεση που εκτοξεύθηκε από προηγούμενο μπλοκ try.
Η catch είναι το δεύτερο μισό της κατασκευής try/catch. Δεν είναι αυτόνομη εντολή: ακολουθεί ένα μπλοκ try, δηλώνει μια λεξιλογική VAR για να λάβει την τιμή της εξαίρεσης, και εκτελεί το BLOCK της μόνο όταν το μπλοκ try πέθανε. Αν το μπλοκ try ολοκληρώθηκε κανονικά, το μπλοκ catch παραλείπεται. Ο έλεγχος συνεχίζει τότε στην εντολή που ακολουθεί ολόκληρη την κατασκευή (ή στο μπλοκ finally, αν υπάρχει).
Αυτή η σύνταξη πρέπει να ενεργοποιηθεί με use feature 'try'. Οι try και catch δεν είναι πειραματικές από την Perl 5.40 και μετά.
Σύνοψη#
try BLOCK catch (VAR) BLOCK
try BLOCK catch (VAR) BLOCK finally BLOCK
Τι επιστρέφεται#
Η catch δεν είναι κλήση συνάρτησης και δεν έχει επιστροφή με την έννοια της έκφρασης. Όπως άλλες κατασκευές ροής ελέγχου, η τιμή ολόκληρης της try/catch είναι η τιμή του μπλοκ που εκτελέστηκε τελευταίο - χρήσιμο μέσα σε μπλοκ do ή ως ουραία έκφραση μιας υπορουτίνας:
my $value = do {
try {
fetch_thing(@args);
}
catch ($e) {
warn "fetch failed: $e";
$DEFAULT;
}
};
Αν η try εκτελέστηκε μέχρι το τέλος, η κατασκευή αποδίδει την τελευταία τιμή του μπλοκ try και η VAR δεν δένεται ποτέ. Αν η try πέθανε, η κατασκευή αποδίδει την τελευταία τιμή του μπλοκ catch.
Η δήλωση VAR#
The parentheses after catch are mandatory and must contain exactly one scalar variable declaration. It behaves like a my declaration
the
mykeyword is implicit, as in subroutine signatures:
catch ($e) { ... } # $e is a new lexical
catch (my $e) { ... } # syntax error - 'my' is already implied
Η VAR έχει εμβέλεια μόνο μέσα στο μπλοκ catch. Δεν είναι ορατή στο προηγούμενο μπλοκ try, σε οποιοδήποτε επόμενο μπλοκ finally, ούτε μετά την κατασκευή. Η τιμή της είναι ό,τι εκτόξευσε το μπλοκ try - μια συμβολοσειρά, μια λίστα που μετατράπηκε σε συμβολοσειρά, ή μια αναφορά, τυπικά ένα blessed αντικείμενο εξαίρεσης. Δείτε την die για το πώς παράγεται η τιμή της εξαίρεσης.
Σε αντίθεση με την eval, η catch δεν διαβάζει ούτε καθαρίζει το $@· η εξαίρεση ταξιδεύει απευθείας μέσω της VAR. Το $@ παραμένει ανέγγιχτο από την κατασκευή.
Καθολική κατάσταση που επηρεάζει#
Η ίδια η catch δεν επηρεάζει καμία ειδική μεταβλητή. Η κατασκευή try/catch στο σύνολό της αφήνει το $@ αμετάβλητο - σκόπιμη απόκλιση από την eval που έχει σκοπό να αποτρέψει τους καλούντες από το να συγχέουν τα δύο ιδιώματα. Αν χρειάζεστε επιθεώρηση τύπου $@, χρησιμοποιήστε την eval αντί γι” αυτό.
Παραδείγματα#
Σύλληψη μιας απλής εξαίρεσης συμβολοσειράς και αναφορά της:
use feature 'try';
try {
risky();
}
catch ($e) {
warn "risky failed: $e";
}
Επιθεώρηση ενός δομημένου αντικειμένου εξαίρεσης:
try {
process($record);
}
catch ($e) {
if (ref($e) && $e->isa('My::NotFound')) {
return; # missing is fine
}
die $e; # re-throw everything else
}
Επανεκπομπή αμετάβλητης με die. Επειδή η catch δεν αγγίζει το $@, επανεκπέμπετε τη μεταβλητή που δεσμεύσατε, όχι το $@:
try {
step();
}
catch ($e) {
log_error($e);
die $e; # propagates to the next handler
}
Παραγωγή τιμής από την κατασκευή χωρίς return. Η χρήση της return μέσα σε try ή catch επιστρέφει από την περικλείουσα υπορουτίνα, όχι από την κατασκευή - δείτε Οριακές περιπτώσεις:
sub safe_parse {
my ($text) = @_;
try {
parse($text);
}
catch ($e) {
warn "parse error: $e";
undef; # value of the catch block
}
}
Ένα μπλοκ catch που το ίδιο πεθαίνει - η νέα εξαίρεση διαδίδεται προς τα έξω στον επόμενο περικλείοντα χειριστή (try/catch, eval, ή έξοδος προγράμματος):
try {
open_db();
}
catch ($e) {
cleanup();
die "open_db failed: $e"; # thrown from inside catch
}
Οριακές περιπτώσεις#
Δεν μπορεί να σταθεί μόνη της. Το
catch (VAR) { ... }χωρίς προηγούμενο μπλοκtryείναι συντακτικό σφάλμα. Ηcatchαναλύεται ως μέρος της κατασκευήςtry, όχι ως ανεξάρτητη δεσμευμένη λέξη.Ακριβώς ένα βαθμωτό στις παρενθέσεις. Οι παρενθέσεις είναι υποχρεωτικές, πρέπει να δηλώνουν ακριβώς ένα βαθμωτό, και η
myυπονοείται. Τοcatch { ... }χωρίς παρενθέσεις είναι συντακτικό σφάλμα.Η
VARέχει εμβέλεια μπλοκ. Υπάρχει μόνο μέσα στο μπλοκcatch. Ένα μπλοκfinallyπου ακολουθεί δεν τη βλέπει.Οι ψευδείς εξαιρέσεις εξακολουθούν να ενεργοποιούν τον χειριστή. Η
tryδιακρίνει το «πέθανε» από το «ολοκληρώθηκε κανονικά» με μια σημαία που τίθεται κατά το ξετύλιγμα, όχι με την αληθότητα της τιμής εξαίρεσης. Ταdie 0,die ""καιdie undefεισέρχονται όλα στο μπλοκcatch· ηVARλαμβάνει την τιμή όπως εκτοξεύθηκε (με τον συνηθισμένο εξαναγκασμό τηςdieτουundefσε"Died at ...").Το
$@δεν τίθεται. Κώδικας που αναζητά το$@μέσα σε μπλοκcatchδιαβάζει το$@του καλούντος, όχι την εξαίρεση που μόλις συνέλαβε. Χρησιμοποιήστε τηνVAR.Ένα μπλοκ
catchμπορεί να πεθάνει. Οι εξαιρέσεις που εγείρονται μέσα στοcatchδεν συλλαμβάνονται εκ νέου από την ίδια κατασκευή. Διαδίδονται στον επόμενο περικλείοντα χειριστή. Αυτός είναι ο μηχανισμός για επανεκπομπή (die $e) και για αναφορά αποτυχιών καθαρισμού από τον ίδιο τον χειριστή.Η
returnμέσα στοcatchεπιστρέφει από την περικλείουσα υπορουτίνα, όχι από το μπλοκcatch. Αυτό διαφέρει από τοevalBLOCK, όπου ηreturnθα έβγαινε μόνο από τηνeval. Για να αποδώσετε τιμή από την κατασκευή, χρησιμοποιήστε την τελική έκφραση του μπλοκ αντί τηςreturn.Τα στοιχεία ελέγχου βρόχου (
last,next,redo) μέσα στοcatchστοχεύουν περικλείοντα βρόχο, όχι την κατασκευή. Η κατασκευήtry/catchδεν αποτελεί η ίδια βρόχο.Η
caller()δεν βλέπει το πλαίσιοcatch. Επειδή ηcatchδεν παρεμποδίζει τηνreturn, είναι αόρατη στηνcaller, όπως είναι και ταwhileήforeach.Συνδυάζεται μόνο με την αμέσως προηγούμενη
try. Δεν μπορείτε να έχετε δύο μπλοκcatch, ούτε να τοποθετήσετε εντολές μεταξύtryκαιcatch. Το προαιρετικό μπλοκfinally, αν υπάρχει, πρέπει να ακολουθεί τηνcatch.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
try- το μπλοκ του οποίου την αποτυχία χειρίζεται αυτή ηcatch· πάντοτε συνδυάζεται με ακριβώς μίαcatchfinally- προαιρετικό τρίτο μπλοκ που εκτελείται ανεξάρτητα από το αν πέθανε το μπλοκtry· δεν μπορεί να κάνειreturnή να χρησιμοποιήσει στοιχεία ελέγχου βρόχουdie- παράγει την τιμή εξαίρεσης που λαμβάνει ηVAR· χρησιμοποιήστε την μέσα στοcatchγια επανεκπομπήeval- παλαιότερο ιδίωμα χειρισμού εξαιρέσεων που χρησιμοποιεί το$@· σε νέο κώδικα προτιμήστε τηνtry/catchγια σαφέστερη εμβέλεια και χωρίς παγίδες του$@$@- παραμένει ανέγγιχτο από τηνtry/catch· επιθεωρήστε τηνVARαντί γι” αυτό