last#
Εγκαταλείπει αμέσως έναν βρόχο, παραλείποντας το υπόλοιπο του σώματος και το μπλοκ continue.
Η last είναι το αντίστοιχο του break της C στην Perl. Μεταφέρει τον έλεγχο εκτός του περικλείοντος βρόχου στην εντολή που ακολουθεί. Οι υπόλοιπες εντολές της τρέχουσας επανάληψης δεν εκτελούνται, ούτε το μπλοκ continue του βρόχου - αυτή είναι η βασική διαφορά από τη next. Χωρίς όρισμα στοχεύει τον πιο εσωτερικό περικλείοντα while, until, for, foreach ή γυμνό μπλοκ· με LABEL στοχεύει έναν επώνυμο βρόχο πιο έξω.
Σύνοψη#
last
last LABEL
last EXPR # LABEL computed at runtime, since 5.18
Τι επιστρέφεται#
Τίποτα. Η last εκτελεί έλεγχο ροής· δεν παράγει τιμή. Δεν μπορεί να χρησιμοποιηθεί για να επιστρέψει αποτέλεσμα από μπλοκ που κανονικά αποδίδει ένα, όπως eval { ... }, sub { ... }, ή do { ... }. Σε αυτά τα περιβάλλοντα είτε η κατασκευή δεν παράγει τιμή είτε το πρόγραμμα πεθαίνει με Can't "last" outside a loop block - δείτε Οριακές περιπτώσεις παρακάτω.
Στόχευση βρόχου με ετικέτα#
Χωρίς ετικέτα, η last αναφέρεται στον πιο εσωτερικό περικλείοντα βρόχο. Αυτό είναι συνήθως αυτό που θέλετε:
while (my $line = <$fh>) {
last if $line =~ /^__END__$/;
process($line);
}
Με μια ετικέτα μπορείτε να εγκαταλείψετε έναν εξωτερικό βρόχο μέσα από έναν εμφωλευμένο. Οι ετικέτες είναι συμβατικά εξ ολοκλήρου κεφαλαία:
OUTER: for my $row (@grid) {
for my $cell (@$row) {
last OUTER if $cell eq 'STOP';
}
}
# control resumes here
Η last EXPR (Perl 5.18+) υπολογίζει την ετικέτα κατά τον χρόνο εκτέλεσης. Η EXPR πρέπει να αποτιμηθεί σε συμβολοσειρά που κατονομάζει μια περικλείουσα ετικέτα:
my $target = 'OUTER';
last $target;
Αλληλεπίδραση με μπλοκ continue#
Το μπλοκ continue ενός βρόχου εκτελείται κανονικά στο τέλος κάθε επανάληψης, περιλαμβανομένης της τελευταίας. Η last το παραλείπει - αυτή είναι η οριστική διαφορά της από τη next:
my $i = 0;
while ($i < 10) {
last if $i == 3;
print "body $i\n";
} continue {
$i++; # runs after every iteration EXCEPT
# the one terminated by last
}
# prints body 0, body 1, body 2; then exits the loop.
# $i stays at 3 because continue did not fire the final time.
Αν θέλετε να εκτελεστεί η continue, χρησιμοποιήστε αντί γι” αυτό τη next με φύλακα, ή προωθήστε τον μετρητή πριν την last.
Συμπεριφορά σε εμφωλευμένους βρόχους#
Η last εγκαταλείπει μόνο έναν βρόχο τη φορά - τον πιο εσωτερικό, εκτός αν φέρει ετικέτα. Σε αυτό το παράδειγμα η εσωτερική last εγκαταλείπει τη for αλλά η while συνεχίζει να εκτελείται:
while (1) {
for my $x (1 .. 5) {
last if $x == 3;
}
# control lands here every iteration of the while
last; # needed to exit the while as well
}
Για να ξετυλίξετε πολλά επίπεδα ταυτόχρονα, βάλτε ετικέτα στον εξωτερικό βρόχο και στοχεύστε τον:
SEARCH: for my $file (@files) {
open my $fh, '<', $file or next;
while (my $line = <$fh>) {
if ($line =~ /$pattern/) {
$found = $file;
last SEARCH; # exits both the while and the for
}
}
}
Τα γυμνά μπλοκ μετράνε ως βρόχοι#
Ένα γυμνό μπλοκ { ... } είναι, για σκοπούς ελέγχου ροής, ένας βρόχος που εκτελείται ακριβώς μία φορά. Η last μπορεί να εγκαταλείψει τέτοιο μπλοκ πρόωρα, που είναι ο ιδιωματικός τρόπος για να γράψετε «δοκίμασε μια ακολουθία ελέγχων, βγες στο πρώτο ταίριασμα»:
{
last if $cached;
recompute();
store_in_cache();
}
# control continues here
Αυτή είναι η μόνη μορφή της last που δεν περιλαμβάνει επαναληπτική κατασκευή.
Παραδείγματα#
Σταματήστε την ανάγνωση αρχείου σε κενή γραμμή - το κλασικό ιδίωμα τερματιστή κεφαλίδας:
LINE: while (<$fh>) {
last LINE if /^$/;
push @header, $_;
}
Εύρεση-και-αναφορά σε δισδιάστατη δομή:
my $hit;
ROW: for my $r (0 .. $#grid) {
for my $c (0 .. $#{ $grid[$r] }) {
if ($grid[$r][$c] eq $needle) {
$hit = [$r, $c];
last ROW;
}
}
}
Πρόωρη έξοδος από γυμνό μπλοκ που χρησιμοποιείται ως ακολουθία try-once:
my $result;
{
$result = $cache{$key}, last if exists $cache{$key};
$result = compute($key);
$cache{$key} = $result;
}
Υπολογισμένη ετικέτα (Perl 5.18+). Σπάνια απαιτείται, αλλά χρήσιμο όταν ο βρόχος-στόχος επιλέγεται δυναμικά:
my $level = $deep ? 'OUTER' : 'INNER';
OUTER: for (...) {
INNER: for (...) {
last $level if $done;
}
}
Οριακές περιπτώσεις#
Παράνομη σε
grepκαιmap. Και οι δύο περιμένουν το μπλοκ τους να παράγει τιμή για κάθε στοιχείο εισόδου· ηlastτο αποκλείει. Ο αναλυτής δέχεται τον κώδικα (το μπλοκ δεν είναι λεξιλογικά βρόχος μέσα από τον οποίο μπορεί να δει), αλλά η εκτέλεσή του πεθαίνει μεCan't "last" outside a loop block. Φιλτράρετε με υπό συνθήκη μέσα στο μπλοκ αντί γι” αυτό, ή μεταβείτε σε ρητό βρόχοfor.Το
do { ... }δεν είναι βρόχος. Ηlastμέσα σεdo { ... }δεν τερματίζει τηdo· ξετυλίγει στον κοντινότερο περικλείοντα πραγματικό βρόχο. Αν δεν υπάρχει, το πρόγραμμα πεθαίνει μεCan't "last" outside a loop block. Για πρόωρη έξοδο από μιαdoπου χρησιμοποιείται ως έκφραση, δείτε τα workarounds στο perlsyn υπό «Statement Modifiers» - τυπικά γυμνό μπλοκ συνlast, ή βρόχοςforμίας εκτέλεσης.Η
sub { ... }δεν είναι βρόχος. Ηlastμέσα σε σώμα sub δεν επιστρέφει από τη sub· ξετυλίγει πέρα από τη sub στον περικλείοντα βρόχο στον καλούντα. Χρησιμοποιήστεreturnγια να φύγετε από μια sub.Η
lastμέσα σεevalδεν διαφεύγει τηςeval. Ηeval { ... }δεν είναι η ίδια βρόχος, οπότε ηlastκοιτάζει προς τα έξω πέρα από τηνevalγια τον κοντινότερο περικλείοντα βρόχο και ξετυλίγει σε αυτόν. Ηevalεγκαταλείπεται ως παρενέργεια αυτού του ξετυλίγματος, αλλά το$@μένει κενό - δεν εγέρθηκε εξαίρεση. Αν ηevalδεν έχει περικλείοντα βρόχο από πάνω, το πρόγραμμα πεθαίνει μεCan't "last" outside a loop block. Για να φύγετε κανονικά από μιαeval, αφήστε την ροή να τελειώσει ή χρησιμοποιήστεdie(συλλαμβάνεται από την ίδια τηνeval) ήreturn(αν ηevalβρίσκεται μέσα σε sub και θέλετε να φύγετε από τη sub).Προτεραιότητα. Σε αντίθεση με τους περισσότερους ονομασμένους τελεστές, η
lastέχει την ίδια προτεραιότητα με την εκχώρηση και εξαιρείται από τον κανόνα «μοιάζει με συνάρτηση». Έτσι τοlast ("foo") . "bar"περνά το"foo" . "bar"ως ετικέτα, όχι μόνο το"foo". Χρησιμοποιήστε κενό, ή παραλείψτε τις παρενθέσεις, για να αποφύγετε εκπλήξεις:last LABEL; last "LABEL";
Άγνωστη ετικέτα. Η
last NOPEόπου κανένας περικλείων βρόχος δεν φέρει την ετικέταNOPEπεθαίνει μεLabel not found for "last NOPE". Αυτό είναι σφάλμα χρόνου εκτέλεσης, όχι μεταγλώττισης - η ετικέτα επιλύεται έναντι της δυναμικής στοίβας κλήσεων.Η μορφή τροποποιητή βρόχου δεν έχει μπλοκ προς έξοδο. Το
EXPR if CONDκαι παρόμοιες μορφές τροποποιητή εντολής δεν είναι βρόχοι· ηlastμέσα στην έκφραση ξετυλίγει πέρα από αυτές.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
next- μεταβείτε στην επόμενη επανάληψη, εκτελώντας πρώτα το μπλοκcontinue· το αντίστοιχο τηςlastπου κρατά τον βρόχο ζωντανόredo- επανεκκινήστε την τρέχουσα επανάληψη χωρίς να επανελέγξετε τη συνθήκη και χωρίς να εκτελέσετε τηνcontinuereturn- φύγετε από υπορουτίνα με τιμή· το σωστό εργαλείο όταν αναζητάτε τηνlastμέσα σεsub { ... }continue- το μπλοκ-ουραίο του βρόχου που ηlastπαραλείπει και ηnextτιμά· διαβάστε τη σελίδα του για την τριμερή απεικόνιση τωνlast/next/redo