return#
Φεύγει από την τρέχουσα υπορουτίνα, eval, do FILE, μπλοκ sort, ή μπλοκ eval regex, αποδίδοντας μια τιμή στον καλούντα.
Η return είναι η ρητή έξοδος από ονοματισμένη ή ανώνυμη υπορουτίνα. Σταματά την αξιολόγηση του σώματος της υπορουτίνας στο σημείο κλήσης και παραδίδει την EXPR πίσω σε όποιον κάλεσε την υπορουτίνα. Η τιμή που παράγει η EXPR εξαρτάται από το περιβάλλον του καλούντος - λίστας, βαθμωτό ή κενό - το οποίο το σώμα μπορεί να ελέγξει με wantarray πριν αποφασίσει τι να επιστρέψει.
Σύνοψη#
return EXPR
return
Τι επιστρέφεται#
Η ίδια η return δεν έχει τιμή επιστροφής - δεν συνεχίζει στο τρέχον πλαίσιο. Τερματίζει το πλαίσιο και ο καλών λαμβάνει την EXPR, αξιολογημένη στο περιβάλλον του καλούντος:
Περιβάλλον λίστας - η
EXPRαξιολογείται σε περιβάλλον λίστας· η τιμή λίστας της είναι αυτό που βλέπει ο καλών.Βαθμωτό περιβάλλον - η
EXPRαξιολογείται σε βαθμωτό περιβάλλον· η βαθμωτή τιμή της είναι αυτό που βλέπει ο καλών.Κενό περιβάλλον - η
EXPRαξιολογείται ακόμη (για παρενέργειες), αλλά η τιμή απορρίπτεται.
Χωρίς EXPR ο καλών λαμβάνει:
περιβάλλον λίστας - την κενή λίστα
()βαθμωτό περιβάλλον -
undefκενό περιβάλλον - τίποτα
Αυτή η ασυμμετρία έχει σημασία: το 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:
Η
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.
Παράνομο: return μέσα σε grep / map:
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εκτός κι αν θέλετε συγκεκριμένα ορισμένο βαθμωτό με τιμή 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. Σπάνια χρήσιμο· η κανονική ροή μπλοκ είναι σχεδόν πάντα σαφέστερη.Οι παρενέργειες σε κενό περιβάλλον συμβαίνουν παρ” όλα αυτά: το
return expensive();σε κενό περιβάλλον εξακολουθεί να καλεί τηνexpensive(). Ηreturnδεν είναι υπόδειξη βελτιστοποίησης.Όχι συνάρτηση, δεν χρειάζονται παρενθέσεις: η
returnείναι τελεστής, όχι συνάρτηση. Ταreturn(1, 2, 3)καιreturn 1, 2, 3είναι ίδια. Η εξαίρεση του αναλυτή παραπάνω σημαίνει ότι οι παρενθέσεις γύρω από τηνEXPRδεν την οριοθετούν από το υπόλοιπο της εντολής - οι παρενθέσεις είναι αμιγώς για ομαδοποίηση μέσα στηνEXPR.Επιστροφή σε μορφή μπλοκ της
eval: τοeval { return $x }φεύγει από τοevalμε$x· το$@καθαρίζει (καμία εξαίρεση). Για επιστροφή από την περικλείουσα υπορουτίνα μέσω εξαίρεσης, χρησιμοποιήστεdieαντ” αυτού.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
wantarray- ελέγχει το περιβάλλον του καλούντος ώστε ηreturnνα αποδώσει το σωστό σχήμαcaller- το άλλο μισό της ενδοσκόπησης καλούντος· χρήσιμη όταν μια υπορουτίνα αποφασίζει τι θα επιστρέψει με βάση το ποιος την κάλεσεeval- ηreturnμέσα σε μπλοκevalφεύγει από τοeval, όχι από την περικλείουσα υπορουτίναsub- πώς ορίζονται οι υπορουτίνες και πώς η έμμεση επιστροφή αλληλεπιδρά με την τελευταία έκφρασηdie- η μη τοπική έξοδος· χρησιμοποιήστε όταν θέλετε να ξετυλίξετε πέρα από ενδιάμεσα πλαίσια αντί να επιστρέφετε μέσα από καθένα τουςlast- εξέρχεται από βρόχο, όχι από υπορουτίνα· μη μπερδεύετε τα δύο