next#
התחלה מיידית של האיטרציה הבאה של הלולאה העוטפת.
next הוא המקבילה של Perl להוראת continue של C: הוא נוטש את שאר גוף האיטרציה הנוכחית וקופץ לשלב האיטרציה של הלולאה. אם ללולאה יש בלוק 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ליציאה מהם הוא שימוש שגוי ומצוין במפורש ב־perlfunc של upstream. השתמשו בביטוי תנאי במקום זאת: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"));
Thread־ים, אותות, הורסים.
nextמשחרר את התחום הלקסיקלי של האיטרציה הנוכחית: משתניmyיוצאים מהתחום, ערכיlocalמשוחזרים, ו־DESTROYיורה על עצמים שיוצאים מהתחום, בדיוק כאילו האיטרציה הסתיימה כרגיל. מטפלי$SIG{...}ממתינים אינם מושפעים.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
last- יציאה מהלולאה העוטפת לחלוטין, תוך דילוג על כל בלוקcontinueredo- אתחול מחדש של האיטרציה הנוכחית מבלי לבדוק שוב את התנאי ומבלי להריץ אתcontinuereturn- הכלי הנכון ליציאה מ־sub { },eval { }, אוdo { }עם ערך;nextאינו יכול לעשות זאתgrep- סינון רשימה; השתמשו בביטוי תנאי, לא ב־next, להשלכת אלמנטיםmap- שינוי צורה של רשימה; החזירו את הרשימה הריקה()מהבלוק כדי להשליך אלמנט