return#
עוזב את התת־שגרה הנוכחית, eval, do FILE, בלוק sort, או בלוק eval של regex, ומניב ערך לקורא.
return היא היציאה המפורשת מתת־שגרה בעלת שם או אנונימית. היא עוצרת את הערכת גוף התת־שגרה בנקודת הקריאה ומסירה את EXPR בחזרה למי שהפעיל את התת־שגרה. הערך ש־EXPR מייצרת תלוי בהקשר של הקורא - רשימה, סקלר, או void - אותו הגוף יכול לבדוק עם wantarray לפני שמחליטים מה להחזיר.
תקציר#
return EXPR
return
מה מקבלים בחזרה#
ל־return עצמה אין ערך החזרה - היא אינה ממשיכה במסגרת הנוכחית. היא מסיימת את המסגרת והקורא מקבל את EXPR, מוערך בהקשר של הקורא:
הקשר רשימה -
EXPRמוערך בהקשר רשימה; ערך הרשימה שלו הוא מה שהקורא רואה.הקשר סקלר -
EXPRמוערך בהקשר סקלר; ערך הסקלר שלו הוא מה שהקורא רואה.הקשר void -
EXPRעדיין מוערך (לתופעות לוואי), אך הערך מושלך.
ללא EXPR הקורא מקבל:
הקשר רשימה - הרשימה הריקה
()הקשר סקלר -
undefהקשר void - כלום
חוסר הסימטריה הזה חשוב: return; (חשוף) אינה אותו דבר כמו return undef;. return חשוף בהקשר רשימה מניב (), שהוא שקר ובעל אפס אברים; return undef; בהקשר רשימה מניב רשימה בת איבר אחד המכילה undef, שהיא אמת (כי לרשימה איבר אחד). תת־שגרות המאותתות שגיאה צריכות כמעט תמיד להשתמש ב־return חשוף.
sub find_it {
my ($key) = @_;
return unless exists $cache{$key}; # bare: () in list, undef in scalar
return $cache{$key};
}
if (my @hits = find_it($k)) { ... } # () is false; undef-in-list is true
היכן return חוקי#
return משחרר את המסגרות האלה:
תת־שגרה בעלת שם או אנונימית
evalשל מחרוזת או בלוק -returnמתוךeval { ... }עוזב את ה־eval, לא את התת־שגרה העוטפתdo FILE-return EXPRהוא ערך הקובץבלוק משווה של
sort- מחזיר את תוצאת ההשוואהבלוק eval של regex - בלוקי קוד
/(?{ ... })/ו־/(?&NAME)/
return אינו חוקי בתוך הבלוקים האלה - זוהי שגיאת זמן הידור או זמן ריצה תלוי בהקשר:
grep BLOCK LISTו־map BLOCK LIST- הבלוק אינו מסגרת תת־שגרה; יש להשתמש בביטוי האחרון של הבלוק במקום זאתdo BLOCK- הבלוק הוא ביטוי, לא קריאה; ערכו הוא כבר הביטוי האחרון של הבלוקבלוקים חשופים, גופי
if/while/for- מאותה סיבה; אלה אינם מהווים מסגרת קריאה
אם צריך ”להחזיר ערך מהבלוק הזה“, יש להפוך אותו לביטוי המוערך האחרון של הבלוק:
my @evens = grep { $_ % 2 == 0 } @nums; # not: grep { return ... }
התפשטות הקשר עם wantarray#
הקשר הקורא מגיע לנקרא דרך wantarray:
תת־שגרה הרוצה להחזיר ערכים המתאימים לצורה בודקת אותו:
sub stats {
my @xs = @_;
return unless @xs; # bare: () / undef as above
my $sum = 0; $sum += $_ for @xs;
my $avg = $sum / @xs;
return wantarray ? ($sum, $avg) : $avg;
}
my ($s, $a) = stats(@data); # list context → two values
my $a = stats(@data); # scalar context → average only
stats(@data); # void context → computed, discarded
אותו אתר קריאה יכול להיות מוערך בהקשרים שונים בהפעלות שונות; return פותר מחדש את EXPR בכל פעם.
החזרה מובלעת: הביטוי האחרון מנצח#
אם הבקרה מגיעה לסוף של תת־שגרה (או eval, או do FILE) מבלי לפגוש return, ערך הביטוי המוערך האחרון מוחזר, בהקשר של הקורא. זהו הסגנון הניבי של ”ביטוי נגרר“:
sub square { my ($x) = @_; $x * $x } # implicit return of $x * $x
sub classify {
my ($n) = @_;
$n < 0 ? "negative"
: $n == 0 ? "zero"
: "positive" # trailing ternary is the value
}
יש להשתמש ב־return מפורש כשיוצאים מוקדם, או כשסוף התת־שגרה הוא משפט (לדוגמה, לולאה, השמה) שערכו אינו מה שרוצים שהקורא יראה.
דוגמאות#
יציאה מוקדמת על שומר:
sub lookup {
my ($id) = @_;
return unless defined $id;
return $table{$id};
}
חזרה מבלוק eval מבלי לשחרר את התת־שגרה העוטפת:
sub try_parse {
my ($text) = @_;
my $parsed = eval {
return {} if $text eq ""; # leaves eval, not try_parse
parse($text);
};
return $@ ? undef : $parsed;
}
החזרה רגישת־הקשר:
sub users {
return wantarray ? @all_users : scalar @all_users;
}
my @u = users(); # the users themselves
my $n = users(); # how many there are
חריגת מנתח - return אינה אופרטור נראה־כפונקציה:
sub greet { return ("hello") . " world" } # returns "hello world"
# the . " world" is part of EXPR
greet(); # "hello world"
לכן return (EXPR) אינה מבודדת את EXPR מאופרטור נגרר; כל מה שאחרי הסוגר הסוגר הוא עדיין ארגומנט ל־return. אותו כלל כמו print.
my @odd = grep { return $_ % 2 } @n; # wrong; leaves the sub
my @odd = grep { $_ % 2 } @n; # right
בתוך grep / map הביטוי האחרון של הבלוק הוא כבר הערך; return שם יוצא מ־התת־שגרה העוטפת, וזה כמעט אף פעם לא מה שמתכוונים אליו.
מקרי קצה#
returnחשוף מולreturn undef: כאמור לעיל,returnחשוף מניב()בהקשר רשימה, מה שמאפשר ל־if (my @x = f())לעבוד כבדיקת ”אין תוצאות“.return undefשם איבר אחד ברשימה והופך את הבדיקה הזו לאמת. עדיףreturnחשוף אלא אם רוצים במיוחד סקלר defined-undef.returnממשווהsort: לגיטימי ונפוץ במשווים מורכבים:sort { return $a->[0] <=> $b->[0] || $a->[1] cmp $b->[1] } @rows;
returnמ־do FILE: הופך לערך הקובץ, וזה מה ש־requireו־useבודקים כדי להחליט על הצלחת טעינת מודול..pmהמסתיים ב־1;הוא הניב הנפוץ;return 1;בקרבת ראש הקובץ שקול.returnמבלוק(?{ ... })של regex: מסיים רק את בלוק הקוד, לא את התאמת ה־regex. לעיתים נדירות שימושי; זרימת בלוק רגילה כמעט תמיד ברורה יותר.תופעות לוואי בהקשר void עדיין מתרחשות:
return expensive();בהקשר void עדיין קורא ל־expensive().returnאינה רמז אופטימיזציה.לא פונקציה, לא נדרשים סוגריים:
returnהוא אופרטור, לא פונקציה.return(1, 2, 3)ו־return 1, 2, 3הם אותו דבר. חריגת המנתח לעיל פירושה שסוגריים סביבEXPRאינם מתחמים אותו מיתר המשפט - הסוגריים הם אך ורק לקיבוץ בתוךEXPR.Return בצורת בלוק של
eval:eval { return $x }עוזב את ה־evalעם$x;$@מנוקה (אין חריגה). כדי להחזיר מהתת־שגרה העוטפת דרך חריגה, יש להשתמש ב־dieבמקום זאת.
הבדלים מהמקור#
תואם במלואו ל־Perl 5.42 במקור.
ראו גם#
wantarray- בודק את הקשר הקורא כך ש־returnיוכל להניב את הצורה הנכונהcaller- החצי השני של אינטרוספקציית הקורא; שימושי כשתת־שגרה מחליטה מה להחזיר על סמך מי קרא להeval-returnבתוך בלוקevalעוזב את ה־eval, לא את התת־שגרה העוטפתsub- איך תת־שגרות מוגדרות ואיך החזרה מובלעת מתקיימת באינטראקציה עם הביטוי האחרוןdie- יציאה לא־מקומית; יש להשתמש כשרוצים לשחרר מעבר למסגרות ביניים במקום להחזיר דרך כל אחת מהןlast- יוצא מלולאה, לא מתת־שגרה; אסור לבלבל בין השניים