next#
Ξεκινά αμέσως την επόμενη επανάληψη του περικλείοντος βρόχου.
Η next είναι το ισοδύναμο της εντολής continue της C στην Perl: εγκαταλείπει τα υπόλοιπα του σώματος της τρέχουσας επανάληψης και μεταπηδά στο βήμα επανάληψης του βρόχου. Αν ο βρόχος έχει μπλοκ continue, εκτελείται πρώτα αυτό το μπλοκ, μετά ελέγχεται ξανά η συνθήκη ελέγχου (ή λαμβάνεται το επόμενο στοιχείο για foreach), και η εκτέλεση συνεχίζεται από την κορυφή του σώματος. Με ετικέτα, η next LABEL στοχεύει σε συγκεκριμένο περικλείοντα βρόχο αντί για τον εσώτατο.
Σύνοψη#
next
next LABEL
next EXPR
Τι επιστρέφεται#
Τίποτα. Η next είναι τελεστής ελέγχου ροής, όχι έκφραση - ξετυλίγεται από την τρέχουσα επανάληψη και επομένως ποτέ δεν παράγει τιμή προς τον καλούντα της. Η προσπάθεια χρήσης της σε θέση που παράγει τιμή (για παράδειγμα ως δεξί μέλος ανάθεσης μέσα σε eval {}, sub {} ή do {}) είναι κακή χρήση: η περιβάλλουσα κατασκευή δεν ολοκληρώνεται ποτέ φυσιολογικά, οπότε δεν υπάρχει τιμή επιστροφής για παρατήρηση.
Στόχευση βρόχου#
Χωρίς ετικέτα, η next αναφέρεται στον εσώτατο περικλείοντα βρόχο (while, until, for, foreach, ή σκέτο μπλοκ, το οποίο μετράει ως βρόχος μίας εκτέλεσης). Με ετικέτα αναφέρεται στον κατονομασμένο βρόχο, ανεξαρτήτως του πόσο βαθιά εμφωλευμένη βρίσκεται η next μέσα σε άλλους βρόχους:
OUTER: for my $row (@grid) {
for my $cell (@$row) {
next OUTER if $cell eq 'skip-row';
process($cell);
}
}
Η next EXPR, διαθέσιμη από την Perl 5.18, αποτιμά την EXPR κατά τον χρόνο εκτέλεσης και χρησιμοποιεί την τιμή της ως συμβολοσειρά για το όνομα ετικέτας. Κατά τα άλλα συμπεριφέρεται ακριβώς όπως η next LABEL:
my $target = pick_label();
next $target; # same as: next FOO if $target eq "FOO"
Χρησιμοποιήστε τη μορφή χρόνου εκτέλεσης με φειδώ - η στατική next LABEL είναι ευκολότερο να διαβαστεί και να επαληθευτεί με το μάτι.
Αλληλεπίδραση με μπλοκ continue#
Το μπλοκ continue ενός βρόχου εκτελείται στο τέλος κάθε επανάληψης, είτε αυτή τελείωσε φυσιολογικά είτε μέσω next. Αυτό είναι όλο το νόημα της ύπαρξης μπλοκ continue: ομαδοποιεί τη λογιστική που πρέπει να συμβαίνει σε κάθε πέρασμα.
my $i = 0;
LINE: while (my $line = <$fh>) {
next LINE if $line =~ /^\s*#/; # skip comments
process($line);
}
continue {
$i++; # runs even for skipped lines
}
Η last παρακάμπτει το μπλοκ continue· η next όχι. Αυτή είναι η απλούστερη διακριτική ιδιότητα των δύο, και ο λόγος που το continue υπάρχει ως ξεχωριστή κατασκευή αντί να ενσωματώνεται στο σώμα του βρόχου.
Παραδείγματα#
Βασικός βρόχος while - απόρριψη γραμμών σχολίων, επεξεργασία των υπολοίπων:
while (my $line = <$fh>) {
next if $line =~ /^\s*#/;
next if $line =~ /^\s*$/; # blank
handle($line);
}
foreach με συσσωρευτή - παράκαμψη εγγραφών που αποτυγχάνουν σε κατηγόρημα:
my $total = 0;
for my $n (@values) {
next unless defined $n;
next if $n < 0;
$total += $n;
}
Εμφωλευμένοι βρόχοι με ετικέτα - προχωρούμε στην επόμενη εξωτερική γραμμή μόλις εντοπίσουμε φρουρά στην εσωτερική σάρωση:
ROW: for my $row (@grid) {
for my $cell (@$row) {
next ROW if $cell eq 'END';
count($cell);
}
}
Μπλοκ continue που εκτελείται πάντα, ακόμα και σε next:
my @kept;
ITEM: for my $x (@input) {
next ITEM if $x->{hidden};
push @kept, $x;
}
continue {
log_seen($_); # every $x is logged, kept or not
}
Διαφυγή από σκέτο μπλοκ - ένα αυτόνομο { ... } είναι βρόχος μίας εκτέλεσης, οπότε η next υπερπηδά τις υπόλοιπες εντολές και βγαίνει από αυτό:
{
last_chance() or next; # bare block: next == fall out
commit();
}
Οριακές περιπτώσεις#
Παράνομη μέσα σε
grep/map/ μπλοκ τιμήςdo { }. Αυτές οι κατασκευές δεν είναι βρόχοι - το μπλοκ τους αποτιμάται για την τιμή του, δεν επαναλαμβάνεται με την έννοια του ελέγχου βρόχου. Η χρήση τηςnextγια να βγείτε από αυτά είναι κακή χρήση και επισημαίνεται ρητά στο upstream perlfunc. Χρησιμοποιήστε αντ’ αυτού υπό συνθήκη έκφραση:my @kept = grep { wanted($_) } @xs; # not: grep { next unless ... } my @mapped = map { transform($_) // () } @ys; # empty list == skip
Δεν είναι
return. Ηnextδεν μπορεί να παραδώσει τιμή έξω από μπλοκ που επιστρέφει τιμή όπωςeval { },sub { }ήdo { }. Αν βρεθείτε να καταφεύγετε στηνnextγια να φύγετε από τέτοιο μπλοκ, αυτό που θέλετε είναι ηreturn, ή μια υπό συνθήκη έκφραση που παράγει την τιμή που χρειάζεστε.Ένα σκέτο μπλοκ είναι βρόχος μίας εκτέλεσης. Το
{ ... }χωρίς πρόθεμαwhile/forείναι σημασιολογικά βρόχος που εκτελείται ακριβώς μία φορά, οπότε ηnextβγαίνει από αυτό. Αυτό είναι ενίοτε χρήσιμο για μοτίβα πρόωρης εξόδου, αλλά ηlastείναι η συχνότερη επιλογή επειδή καθιστά την πρόθεση σαφέστερη.Άγνωστη ετικέτα είναι μοιραίο σφάλμα. Η
next NOSUCHπεθαίνει κατά τον χρόνο εκτέλεσης μεCan't "next" outside a loop blockόταν κανένας περικλείων βρόχος δεν φέρει αυτήν την ετικέτα.Το
continueεκτελείται σεnext, όχι σεlast. Αυτή είναι η συνηθισμένη αιτία έκπληξης κατά την αναδιάρθρωση: η μετακίνηση λογιστικής έξω από το σώμα του βρόχου στοcontinueαλλάζει συμπεριφορά μόνο για τηνlast, όχι για τηνnext.Ιδιορρυθμίες προτεραιότητας και ανάλυσης. Σε αντίθεση με τους περισσότερους κατονομασμένους τελεστές, η
nextέχει την ίδια προτεραιότητα με την ανάθεση, και εξαιρείται από τον κανόνα «μοιάζει-με-συνάρτηση». Αυτό σημαίνει ότι ηnext ("foo") . "bar"περνά το"foobar"στηνnext, όχι μόνο το"foo". Χρησιμοποιήστε αμυντικά παρενθέσεις όταν το όνομα ετικέτας προέρχεται από έκφραση:next(($cond ? "A" : "B"));
Threads, σήματα, καταστροφείς. Η
nextξετυλίγει τη λεξιλογική εμβέλεια της τρέχουσας επανάληψης: οι μεταβλητέςmyβγαίνουν από την εμβέλεια, οι τιμέςlocalεπανέρχονται, και οDESTROYπυροδοτείται σε αντικείμενα εξόδου εμβέλειας, ακριβώς όπως αν η επανάληψη είχε τερματιστεί φυσιολογικά. Οι εκκρεμείς χειριστές$SIG{...}δεν επηρεάζονται.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
last- έξοδος από τον περικλείοντα βρόχο τελείως, παρακάμπτοντας κάθε μπλοκcontinueredo- επανεκκίνηση της τρέχουσας επανάληψης χωρίς εκ νέου έλεγχο της συνθήκης και χωρίς εκτέλεση τουcontinuereturn- το σωστό εργαλείο για έξοδο απόsub { },eval { }ήdo { }με τιμή· ηnextδεν μπορεί να το κάνει αυτόgrep- φιλτράρει μια λίστα· χρησιμοποιήστε υπό συνθήκη έκφραση, όχιnext, για να απορρίψετε στοιχείαmap- μετασχηματίζει μια λίστα· επιστρέψτε την κενή λίστα()από το μπλοκ για να απορρίψετε ένα στοιχείο