Τιμές επιστροφής#

Μια 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 ευαίσθητες στο περιβάλλον.

  • Ορίσματα και @_ - η συμμετρική ιστορία για το τι εισέρχεται.

  • die, warn - οι εναλλακτικές αντί για «επιστροφή αποτυχίας».