ערכי החזרה#
תת־שגרה חוזרת או בהגיעה לפקודה האחרונה שלה, או בפגיעה ב־return מפורש, או על־ידי goto למקום אחר (ראה רקורסיה). הרשימה המוחזרת מושטחת באותה דרך שרשימת הארגומנטים מושטחת - מערכים ו־hashes מאבדים את זהותם אלא אם אתה מחזיר הפניות - ולאחר מכן מוערכת בהקשר של הקורא.
החזרה משתמעת#
אם הבקרה נופלת מקצה הגוף, מוחזר ערך פקודת הביטוי האחרונה:
sub square {
my ($x) = @_;
$x * $x # implicit return
}
say square(5); # 25
החזרה משתמעת היא נהוגה עבור תת־שגרות קצרות בעלות ביטוי יחיד. היא אינה נהוגה עבור תת־שגרות רב־ענפיות, שבהן הקוראים נהנים מלראות כל יציאה מסומנת במפורש עם return.
אם הפקודה האחרונה היא מבנה בקרת־זרימה (for, while, if ללא else, …), הערך המוחזר אינו מוגדר. תת־שגרה ריקה מחזירה את הרשימה הריקה.
החזרה מפורשת#
sub max {
my ($a, $b) = @_;
return $a if $a >= $b;
return $b;
}
return מפורש יוצא מתת־השגרה מיד ומספק את ערך ההחזרה. החזרות מוקדמות מרובות הן הצורה הסטנדרטית עבור קוד שמור:
sub fetch {
my ($id) = @_;
return unless defined $id; # void/empty
return undef if $id eq ''; # explicit undef in scalar
...
}
שים לב להבדל בין return; לבין return undef;:
return;מחזיר את הרשימה הריקה בהקשר רשימה,undefבהקשר סקלר, ולא כלום בהקשר void. זוהי הדרך הנכונה־להקשר לומר ”אין תוצאה“.return undef;מחזיר את הרשימה(undef)בהקשר רשימה, שאורכה 1 - כך שקורא הכותבif (my @r = my_sub()) { ... }יראה רשימה בת אבר אחד וה־ifיופעל. זה כמעט תמיד שגוי.
כלל האצבע: כתוב return; כדי לציין כישלון או היעדר; כתוב return undef; רק כשמובטח שהקורא נמצא בהקשר סקלר.
השטחת רשימה בהחזרה#
אותה השטחה החלה על ארגומנטים חלה על ערכי החזרה:
sub two_lists {
my @a = (1, 2);
my @b = (3, 4);
return (@a, @b); # returns (1, 2, 3, 4) - one flat list
}
my ($x, $y) = two_lists(); # $x = 1, $y = 2 ; rest discarded
my @all = two_lists(); # @all = (1, 2, 3, 4)
my (@p, @q) = two_lists(); # @p = (1, 2, 3, 4), @q = ()
השורה האחרונה היא ההפתעה הקלאסית: @p בולע בחמדנות את כל הרשימה משום שלהשמת רשימה למערך שטוח בצד שמאל אין דרך לדעת היכן קבוצה לוגית אחת מסתיימת והבאה מתחילה. כדי להחזיר שני מערכים בנפרד, החזר הפניות:
sub two_lists {
return (\@a, \@b);
}
my ($pref, $qref) = two_lists();
החזרה רגישת־הקשר#
sub items {
if (wantarray) {
return (1, 2, 3); # list context
}
elsif (defined wantarray) {
return 3; # scalar context: count
}
else {
return; # void: nothing to compute
}
}
my @list = items(); # (1, 2, 3)
my $cnt = items(); # 3
items(); # discarded
ענף ה“החזרה המוקדמת ב־void“ הוא תבנית אופטימיזציה אמיתית - חישובים יקרים לא צריכים לרוץ כשהקורא זורק את התוצאה.
לדיון המלא ב־wantarray וכיצד הוא מתחבר עם :lvalue, ראה lvalue והקשר.
החזרת hashes ומערכים#
החזרת @array או %hash ישירות עובדת רק בזכות ההשטחה:
sub config {
return (host => 'localhost', port => 80);
}
my %c = config(); # %c is the hash
my @c = config(); # @c = ('host', 'localhost', 'port', 80)
עבור מבנים גדולים יותר, החזר הפניות:
sub config {
my %c = (host => 'localhost', port => 80);
return \%c; # one ref, no flattening
}
my $c = config();
say $c->{host};
הפניות הן גם הדרך היחידה להחזיר מספר צברים מבלי שהקורא יצטרך לדעת את גדליהם.
return בתוך eval#
return בתוך בלוק do {} או eval {} חוזר מתת־השגרה העוטפת, לא מהבלוק:
sub safe {
my $result = eval {
return 'inside'; # this returns from `safe`, not from eval
};
return $result; # never reached
}
כדי לצאת רק מה־eval, השתמש בערך ('inside' כביטוי האחרון של הבלוק) - eval מחזיר את ערך הביטוי האחרון שלו כמו כל בלוק אחר.
החזרה מ־BEGIN/END#
הבלוקים BEGIN, END, INIT, CHECK, ו־UNITCHECK הם תת־שגרות במובן הטכני אך ערך ההחזרה שלהם נזרק. אל תטרח לכתוב return ... בתוכם.
ראו גם#
return- עמוד ה־perlfunc של מילת המפתח.wantarray- מה הקורא שלך רוצה בחזרה.תת־שגרות lvalue והקשר - התמונה המלאה עבור תת־שגרות רגישות־הקשר.
ארגומנטים ו־
@_- הסיפור הסימטרי עבור מה שנכנס.