Τιμές επιστροφής#
Μια sub επιστρέφει είτε φτάνοντας στην τελευταία δήλωσή της, είτε συναντώντας ρητό return, είτε μέσω goto αλλού (δείτε αναδρομή). Η λίστα επιστροφής ισοπεδώνεται με τον ίδιο τρόπο όπως η λίστα ορισμάτων - πίνακες και hashes χάνουν την ταυτότητά τους εκτός αν επιστρέψετε αναφορές - και στη συνέχεια αποτιμάται στο περιβάλλον του καλούντος.
Σιωπηρή επιστροφή#
Αν ο έλεγχος πέσει από το τέλος του σώματος, επιστρέφεται η τιμή της τελευταίας δήλωσης έκφρασης:
sub square {
my ($x) = @_;
$x * $x # implicit return
}
say square(5); # 25
Η σιωπηρή επιστροφή είναι ιδιωματική για σύντομες subs μίας έκφρασης. Δεν είναι ιδιωματική για subs πολλαπλών κλάδων, όπου οι αναγνώστες ωφελούνται από τη ρητή σήμανση κάθε εξόδου με return.
Αν η τελευταία δήλωση είναι κατασκευή ελέγχου ροής (ένα for, while, if χωρίς else, …), η τιμή επιστροφής είναι απροσδιόριστη. Η κενή sub επιστρέφει κενή λίστα.
Ρητή επιστροφή#
sub max {
my ($a, $b) = @_;
return $a if $a >= $b;
return $b;
}
Η ρητή return εξέρχεται αμέσως από τη sub και παρέχει την τιμή επιστροφής. Οι πολλαπλές πρόωρες επιστροφές είναι η τυπική μορφή για κώδικα με φρουρούς:
sub fetch {
my ($id) = @_;
return unless defined $id; # void/empty
return undef if $id eq ''; # explicit undef in scalar
...
}
Σημειώστε τη διαφορά μεταξύ return; και return undef;:
Η
return;επιστρέφει κενή λίστα σε περιβάλλον λίστας,undefσε βαθμωτό περιβάλλον, και τίποτα σε κενό περιβάλλον. Είναι ο σωστός ανάλογα με το περιβάλλον τρόπος να πείτε «κανένα αποτέλεσμα».Η
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
Ο κλάδος «πρόωρη επιστροφή σε κενό περιβάλλον» είναι ένα πραγματικό μοτίβο βελτιστοποίησης - ακριβοί υπολογισμοί δεν πρέπει να εκτελούνται όταν ο καλών πετάει το αποτέλεσμα.
Για πλήρη συζήτηση σχετικά με τη 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, όχι από το μπλοκ:
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 είναι subs με την τεχνική έννοια αλλά η τιμή επιστροφής τους απορρίπτεται. Μην μπαίνετε στον κόπο να γράψετε return ... μέσα σε αυτά.
Δείτε επίσης#
return- η σελίδα perlfunc της δεσμευμένης λέξης.wantarray- τι θέλει πίσω ο καλών.Lvalue subs και περιβάλλον - η πλήρης εικόνα για subs ευαίσθητες στο περιβάλλον.
Ορίσματα και
@_- η συμμετρική ιστορία για το τι εισέρχεται.