Ροή ελέγχου

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

Διάδοση περιβάλλοντος με wantarray#

Το περιβάλλον του καλούντος φτάνει στον καλούμενο μέσω της wantarray:

  • Η wantarray είναι αληθής σε περιβάλλον λίστας

  • Η wantarray είναι ορισμένη και ψευδής ("") σε βαθμωτό περιβάλλον

  • Η wantarray είναι undef σε κενό περιβάλλον

Μια υπορουτίνα που θέλει να επιστρέψει τιμές κατάλληλου σχήματος την ελέγχει:

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 - εξέρχεται από βρόχο, όχι από υπορουτίνα· μη μπερδεύετε τα δύο