Δήλωση#
Κάθε sub είναι ένα από τρία πράγματα: μια κατονομασμένη sub δεσμευμένη σε πακέτο, μια ανώνυμη sub αποθηκευμένη σε αναφορά κώδικα, ή μια λεξιλογική sub δεσμευμένη σε μια θέση τύπου my στην τρέχουσα εμβέλεια. Η μορφή δήλωσης επιλέγει μία· όλα τα υπόλοιπα (πρωτότυπο, υπογραφή, γνωρίσματα, σώμα) τη διακοσμούν.
Κατονομασμένες subs#
sub greet {
my ($name) = @_;
return "Hello, $name!";
}
greet("Alice"); # "Hello, Alice!"
Το όνομα greet δεσμεύεται στον πίνακα συμβόλων του τρέχοντος πακέτου κάτω από την υποδοχή ampersand & - την ίδια υποδοχή που αναζητά ο χρόνος εκτέλεσης όταν καλείτε greet(...) ή \&greet. Οι κατονομασμένες subs είναι ορατές σε κάθε κώδικα που εκτελείται μετά τη μεταγλώττιση της δήλωσης sub· στην πράξη «μεταγλωττίστηκε» σημαίνει «το αρχείο αναλύθηκε μέχρι τη δήλωση», κάτι που σχεδόν πάντα είναι αυτό που θέλετε.
Μια κατονομασμένη sub μπορεί επίσης να δηλωθεί σε δύο μέρη - μια προδήλωση και ένας ορισμός:
sub later; # promise: a sub named 'later' will exist
sub later { # fulfilment
return 42;
}
Η προδήλωση είναι κυρίως χρήσιμη όταν τα πρωτότυπα πρέπει να τεθούν σε ισχύ για αναδρομικές κλήσεις (το πρωτότυπο πρέπει να είναι ορατό πριν αναλυθεί η αναδρομική κλήση) ή όταν θέλετε να καταστείλετε τις προειδοποιήσεις «Bareword not allowed» για κώδικα που καλεί τη sub πριν τον ορισμό της.
Κλήση sub με βάση το όνομα#
greet("Alice"); # most common form
greet "Alice"; # parens optional once predeclared
&greet("Alice"); # legacy: disables prototype checking
&greet; # legacy: pass current @_ as the call's @_
Η μορφή σκέτου & (&greet χωρίς παρενθέσεις) είναι ένα κατάλοιπο από τη perl4 με μία εναπομείνασα νόμιμη χρήση: πέρασμα του τρέχοντος @_ κατευθείαν χωρίς αντιγραφή. Δείτε αναδρομή για το goto &greet, την παραλλαγή κλήσης ουράς.
Ανώνυμες subs#
my $double = sub {
my ($x) = @_;
return $x * 2;
};
$double->(7); # 14
Η έκφραση sub { ... } αποτιμάται σε αναφορά κώδικα. Αποτυπώνει οποιεσδήποτε λεξιλογικές μεταβλητές (my/state) από την περικλείουσα εμβέλεια - δείτε εμβέλεια - και καλείται μέσω ->() ή με τις παλαιές μορφές &$double() / &{$double}().
Οι ανώνυμες subs είναι ο τρόπος λειτουργίας κάθε callback στην Perl:
my @sorted = sort { $a <=> $b } @list;
my @big = grep { $_ > 100 } @list;
my @str = map { "<$_>" } @list;
Είναι επίσης το δομικό στοιχείο για closures, πίνακες αποστολής, και αντικείμενα mock. Ένας πίνακας αποστολής:
my %op = (
add => sub { $_[0] + $_[1] },
sub => sub { $_[0] - $_[1] },
mul => sub { $_[0] * $_[1] },
);
my $result = $op{$cmd}->($x, $y);
Αναφορές κώδικα#
Μια αναφορά κώδικα είναι ένα βαθμωτό πρώτης τάξης που κρατά μια sub. Αποκτάτε μία από sub { ... }, από \&named_sub, ή από αναζήτηση μεθόδου με can:
my $cref = \&greet; # ref to named sub
my $cref = sub { ... }; # anonymous
my $cref = $obj->can('method'); # method lookup, returns code ref or undef
$cref->("Alice"); # invocation
&$cref("Alice"); # legacy invocation
Μέσα σε μια αναφορά κώδικα, η sub διατηρεί την ταυτότητά της: η \&greet είναι πάντα η ίδια αναφορά για όλη τη διάρκεια ζωής της &greet του πακέτου. Οι ανώνυμες subs είναι διαφορετικές αναφορές κάθε φορά που αποτιμάται η έκφραση sub { ... } - αυτό κάνει τα εργοστάσια closures να λειτουργούν.
Λεξιλογικές subs#
Μια λεξιλογική sub δηλώνεται με my sub (και τα αντίστοιχα state sub και our sub):
sub outer {
my sub helper {
my ($x) = @_;
return $x * 2;
}
return helper(21); # 42
}
helper(1); # error: undefined subroutine
# (helper isn't visible here)
Η my sub είναι πιο χρήσιμη μέσα σε μεγάλες συναρτήσεις όπου θέλετε ένα ιδιωτικό βοηθητικό χωρίς να μολύνετε τον χώρο ονομάτων του πακέτου. Δεν χρησιμοποιείται ευρέως στην πράξη, αλλά είναι το κατάλληλο εργαλείο όταν θέλετε πραγματική ενθυλάκωση. Δείτε εμβέλεια για τις παραλλαγές state και our.
Προδήλωση#
Μια προδήλωση είναι μια δήλωση sub NAME; (χωρίς σώμα, χωρίς αγκύλες). Τρεις λόγοι για να γράψετε μία:
# 1. Allow the sub to be called without parens before it's defined
sub later;
later; # parses as later()
# 2. Make a prototype visible before the body is reached
sub mypush (\@@);
sub mypush (\@@) { ... }
# 3. Document an exported API at the top of the file
sub greet;
sub farewell;
sub welcome;
# ... actual definitions further down
Σε σύγχρονο κώδικα οι λόγοι (1) και (3) είναι κυρίως υφολογικοί. Ο λόγος (2) είναι πραγματική απαίτηση όταν χρησιμοποιείτε πρωτότυπα· δείτε πρωτότυπα.
Τι δεν μπορείτε να κάνετε#
Δεν μπορείτε να ξαναορίσετε μια ενσωματωμένη με
sub print { ... }και να κάνετε την Perl σιωπηρά να χρησιμοποιεί τη δική σας. Η υπερκάλυψη ενσωματωμένων γίνεται μέσωCORE::GLOBAL::printκαι τεκμηριώνεται στα γνωρίσματα και τη σελίδα λεπτομερειώνprototype.Δεν μπορείτε να έχετε δύο κατονομασμένες subs με το ίδιο όνομα στο ίδιο πακέτο χωρίς προειδοποίηση «Subroutine NAME redefined». Είτε μετονομάστε είτε σκοπεύετε πραγματικά τον επαναορισμό (και αποσιωπήστε την προειδοποίηση με
no warnings 'redefine';).Δεν μπορείτε να δώσετε μια προδήλωση και ένα σώμα με διαφορετικά πρωτότυπα. Οι δύο δηλώσεις πρέπει να συμφωνούν.
Δείτε επίσης#
Ορίσματα και
@_- τι βλέπει το σώμα μόλις γίνει η κλήση.Εμβέλεια - τι κάνουν τα
my,our,local, καιstateστις μεταβλητές μέσα στο σώμα.sub- η σελίδα perlfunc της δεσμευμένης λέξης.prototype- ενδοσκόπηση χρόνου εκτέλεσης του πρωτοτύπου μιας sub, και η γέφυρα για υπερκάλυψη ενσωματωμένων.Τελεστής βέλους - επίκληση αναφορών κώδικα μέσω
->().