Προεπιλεγμένες μεταβλητές#

Δύο μεταβλητές κρατούν τους σιωπηρούς τελεστέους της Perl. Η $_ είναι το προεπιλεγμένο βαθμωτό που αμέτρητες ενσωματωμένες διαβάζουν όταν κληθούν χωρίς όρισμα. Η @_ είναι ο πίνακας ορισμάτων κάθε υπορουτίνας. Μαζί ευθύνονται για τις περισσότερες εκπλήξεις «από πού ήρθε αυτή η τιμή;» σε κώδικα Perl.

$_ - το προεπιλεγμένο βαθμωτό#

Η $_ είναι το θέμα: η τιμή για την οποία γίνεται λόγος αυτή τη στιγμή. Ένα τεράστιο πλήθος ενσωματωμένων της Perl τη συμβουλεύεται όταν κληθεί χωρίς ρητό όρισμα:

for my $line (<$fh>) {
    chomp;                      # chomp $line  - but $line was aliased to $_
    print if /\bERROR\b/;       # print $_ if $_ =~ /\bERROR\b/
}

Η πλήρης λίστα ενσωματωμένων που χρησιμοποιούν εξ ορισμού τη $_ περιλαμβάνει chomp, chop, lc, lcfirst, length, pos, print, printf, quotemeta, say, split (προεπιλεγμένο μοτίβο), study, uc, ucfirst, unlink, τους τελεστές m// και s///, τον τελεστή tr///, και τους τελεστές ελέγχου αρχείου <>/-X. Οι σελίδες λεπτομερειών τους κατονομάζουν τη $_ ως προεπιλογή· αυτή η σελίδα είναι η κανονική περιγραφή.

Ψευδωνυμοποίηση μέσα σε for και while#

Ο βρόχος for (και foreach) ψευδωνυμεί τη $_ σε κάθε στοιχείο της λίστας, διαδοχικά:

my @items = (1, 2, 3);
for (@items) {
    $_ *= 2;                     # mutates @items in place
}
# @items is now (2, 4, 6)

Η τροποποίηση της $_ μέσα στον βρόχο τροποποιεί το ίδιο το στοιχείο λίστας. Αυτή είναι πανομοιότυπη συμπεριφορά με τις map, grep, any, all - και τις first και reduce από τη List::Util.

Η while (<$fh>) δεν ψευδωνυμεί - διαβάζει κάθε γραμμή στη $_ ως νέο αντίγραφο. Δεν μπορείτε να γράψετε πίσω στο αρχείο αναθέτοντας στη $_ μέσα σε βρόχο while (<$fh>).

Τοπικοποίηση $_#

Μια υπορουτίνα που θέλει τη δική της $_ χωρίς να διαταράξει αυτή του καλούντος πρέπει να την κάνει local:

sub categorise {
    local $_ = shift;            # decouple from caller's $_
    return 'small'  if /^\d{1,3}$/;
    return 'medium' if /^\d{4,6}$/;
    return 'large';
}

my @sizes;
for ('5', '12345', '999999999') {
    push @sizes, categorise($_); # caller's $_ stays the loop alias
}

Χωρίς τη local, η κλήση categorise() με shift θα λειτουργούσε - αλλά κάθε =~, /.../, ή chomp μέσα σε αυτήν θα διάβαζε ή θα έγραφε σιωπηρά το ψευδώνυμο βρόχου, σπάζοντας την επανάληψη του καλούντος.

Η $_ ως lvalue#

Η $_ είναι μια πραγματική βαθμωτή μεταβλητή· μπορείτε να αναθέσετε σε αυτήν, να πάρετε αναφορά σε αυτήν, και να τη μεταβιβάσετε ως lvalue:

$_ = 'hello';
chomp;                           # nothing to chomp; $_ unchanged
s/l/L/g;                          # $_ is now 'heLLo'

my $ref = \$_;                    # \$_ is the alias's address
$$ref = 'goodbye';               # mutates whatever $_ is currently bound to

Προσέξτε ότι το δεύτερο $$ref θα γράψει σε ό,τι είναι η $_ αυτή τη στιγμή - που μέσα σε βρόχο for είναι το τρέχον στοιχείο λίστας. Αναφορές στη $_ που λήφθηκαν εκτός βρόχου και χρησιμοποιούνται μέσα σε αυτόν σπάνια κάνουν αυτό που εννοούσε ο συγγραφέας.

Λεξιλογική $_#

Οι our $_ και my $_ ήταν πειραματικά χαρακτηριστικά που αφαιρέθηκαν. Η $_ είναι πάντα η καθολική πακέτου· χρησιμοποιήστε local $_ για απομόνωση.

@_ - ορίσματα υπορουτίνας#

Μέσα σε μια υπορουτίνα, η @_ είναι ο πίνακας ορισμάτων που μεταβιβάστηκαν σε αυτή την κλήση. Κάθε στοιχείο είναι ψευδώνυμο προς την έκφραση του καλούντος - η @_ δεν είναι αντίγραφο:

sub double {
    $_[0] *= 2;                  # mutates the caller's variable
}

my $x = 5;
double($x);
# $x is now 10

Γι” αυτό οι περισσότερες subs ξεκινούν με my (...) = @_; - η αποσυσκευασία δημιουργεί αντίγραφα, μετά τα οποία η ρουτίνα δεν μπορεί κατά λάθος να τροποποιήσει την κατάσταση του καλούντος:

sub greet {
    my ($name, $greeting) = @_;  # decoupled from caller
    $greeting //= 'Hello';
    return "$greeting, $name!";
}

Η ψευδωνυμοποίηση είναι περιστασιακά χρήσιμη - είναι ο τρόπος με τον οποίο η chomp(@lines) τροποποιεί κάθε στοιχείο του πίνακα του καλούντος - αλλά σε καθημερινό κώδικα το ιδίωμα αποσυσκευασμένου-αντιγράφου είναι ο κανόνας.

wantarray και το περιβάλλον κλήσης#

Μια sub που θέλει να συμπεριφέρεται διαφορετικά ανάλογα με το αν κλήθηκε σε βαθμωτό, λίστα, ή κενό περιβάλλον εξετάζει τη wantarray:

sub items {
    return wantarray ? (1, 2, 3) : 3;
}

my @list = items();              # (1, 2, 3)
my $cnt  = items();              # 3
items();                          # void - return value discarded

Η @_ και η wantarray είναι τα δύο κομμάτια της εικόνας σύμβασης κλήσης. Η @_ λέει τι μεταβιβάστηκε· η wantarray λέει τι αναμένεται πίσω.

@_ μετά από shift, pop, unshift, push#

Η τροποποίηση της ίδιας της @_ (όχι των στοιχείων της) δεν έχει αποτέλεσμα ψευδωνυμοποίησης στον καλούντα - είναι μια κανονική τοπική μεταβλητή πίνακα. Η shift @_ αφαιρεί το πρώτο όρισμα, αφήνοντας τα υπόλοιπα:

sub method_call {
    my $self = shift;            # standard OO pattern
    my %args = @_;               # rest of args as a hash
    ...
}

Η shift χωρίς ορίσματα μέσα σε υπορουτίνα χρησιμοποιεί εξ ορισμού τη @_, γι” αυτό βλέπετε my $self = shift; παντού.

$_ = shift - περιμένετε, τι;#

Ένα συνηθισμένο παραπλανητικό ιδίωμα:

sub trim {
    $_ = shift;                  # - set caller's $_ - DO NOT DO THIS
    s/^\s+//;
    s/\s+$//;
    return $_;
}

Αυτό το $_ = shift γράφει στην καθολική πακέτου $_, η οποία είναι το θέμα βρόχου του καλούντος αν ο καλών βρίσκεται μέσα σε for. Η λύση είναι η local, όπως παραπάνω:

sub trim {
    local $_ = shift;
    s/^\s+//;
    s/\s+$//;
    return $_;
}

Δείτε επίσης#

  • map, grep - οι πιο συνηθισμένοι καταναλωτές ψευδωνυμοποίησης $_.

  • shift, pop - χρησιμοποιούν εξ ορισμού τη @_ μέσα σε υπορουτίνα.

  • wantarray - η σύντροφος της @_ στην εικόνα σύμβασης κλήσης.

  • local - ο ασφαλής τρόπος ρύθμισης της $_ μέσα σε sub στην οποία ο καλών μπορεί να βρίσκεται σε επανάληψη.

  • Σύνδεση regex - η =~ είναι αυτό που χρησιμοποιείτε όταν δεν θέλετε τη σιωπηρή $_ ως στόχο.