Υπογραφές#
Μια υπογραφή είναι μια λίστα παραμέτρων σε παρενθέσεις που τοποθετείται αμέσως μετά το όνομα της sub (και μετά τα γνωρίσματα), στη θέση - ή επιπλέον - της χειροκίνητης αποσυσκευασίας @_ του σώματος. Οι υπογραφές εισάγουν λεξιλογικές μεταβλητές παραμέτρων, εκτελούν έλεγχο πληθικότητας κατά τον χρόνο κλήσης, και υποστηρίζουν προεπιλεγμένες τιμές και slurpy παραμέτρους.
Signatures stabilised in Perl 5.36; in 5.44 they are a production feature available with one of:
use feature 'signatures'; # explicit feature import
use v5.36; # implicit (signatures + other 5.36 features)
PetaPerl supports the full 5.44 signature syntax.
Βασική μορφή#
use feature 'signatures';
sub add ($x, $y) { # two mandatory positional parameters
return $x + $y;
}
add(2, 3); # 5
add(2); # error: Too few arguments
add(2, 3, 4); # error: Too many arguments
Κάθε $name στην υπογραφή δηλώνει μια λεξιλογική my που λαμβάνει το αντίστοιχο όρισμα. Η πληθικότητα ελέγχεται κατά την κλήση: το σώμα δεν εκτελείται ποτέ αν ο αριθμός είναι λάθος.
Αυτή είναι η πιο συγκεκριμένη βελτίωση σε σχέση με την κλασική μορφή:
# Classic - silently accepts wrong arity
sub add {
my ($x, $y) = @_;
return $x + $y;
}
add(2); # $y is undef; later arithmetic warns
add(2, 3, 4); # third arg silently ignored
Προεπιλεγμένες τιμές#
sub greet ($name, $greeting = 'Hello') {
return "$greeting, $name!";
}
greet('Alice'); # "Hello, Alice!"
greet('Alice', 'Hi'); # "Hi, Alice!"
Η προεπιλεγμένη τιμή είναι μια αυθαίρετη έκφραση που αποτιμάται κάθε φορά που η παράμετρος παραλείπεται (οπότε λειτουργούν τόσο state όσο και υπολογισμός ανά κλήση). Μπορεί να αναφέρεται σε προηγούμενες παραμέτρους:
sub log_event ($message, $level = 'INFO', $prefix = "[$level]") {
print "$prefix $message\n";
}
log_event('starting'); # [INFO] starting
log_event('failure', 'ERROR'); # [ERROR] failure
log_event('done', 'OK', '>>'); # >> done
Μια προεπιλογή = undef είναι ακριβώς ισοδύναμη με «χωρίς προεπιλογή» για την πληθικότητα (η παράμετρος εξακολουθεί να είναι προαιρετική) αλλά τεκμηριώνει την πρόθεση. Χρησιμοποιήστε φρουρούς τύπου //= μέσα στο σώμα για σημασιολογία «η undef σημαίνει χρήση της εφεδρικής τιμής μου».
Προαιρετικές έναντι υποχρεωτικών#
Οι παράμετροι είναι υποχρεωτικές εξ ορισμού. Μια παράμετρος γίνεται προαιρετική:
Δίνοντάς της μια προεπιλεγμένη τιμή (
$x = 42).Τοποθετώντας την μετά από άλλη προαιρετική παράμετρο (μεταβατικά).
Ακολουθούμενη από slurpy
@arrή%hash.
Δεν μπορείτε να έχετε υποχρεωτική παράμετρο μετά από προαιρετική (εκτός μέσω slurpy):
sub bad ($x = 1, $y) { ... } # error: Mandatory parameter follows optional
Παράμετροι slurpy#
Η τελευταία παράμετρος μπορεί να είναι slurpy @list ή %hash. Καταναλώνει όλα τα εναπομείναντα ορίσματα:
sub join_all ($sep, @parts) {
return join $sep, @parts;
}
join_all(', ', 'a', 'b', 'c'); # "a, b, c"
sub configure ($name, %opts) {
$opts{verbose} //= 0;
...
}
configure('demo', verbose => 1, port => 8080);
Το slurpy hash αποτυγχάνει επίσης αν η εναπομείνασα λίστα έχει μονό μήκος:
configure('demo', 'verbose'); # error: Odd-sized list given
Αυτό είναι το πιο χρήσιμο μοτίβο που ξεκλειδώνουν οι υπογραφές: ένα API ονομαστικών παραμέτρων με μία κατά θέση και ένα slurp %opts.
Ανώνυμες παράμετροι#
Ένα $ (ή @, %) χωρίς όνομα είναι ένα placeholder κατά θέση:
sub second ($, $x) { return $x }
second('ignored', 'kept'); # "kept"
Αυτό είναι ελαφρώς χρήσιμο όταν προσαρμόζετε ένα callback σε μια διεπαφή που παρέχει περισσότερα ορίσματα από όσα σας ενδιαφέρουν.
Συνδυασμός προεπιλεγμένων τιμών και slurpy#
sub render ($template, $cache = 1, %opt) {
...
}
render('greeting.tt'); # cache=1, %opt empty
render('greeting.tt', 0); # cache=0, %opt empty
render('greeting.tt', 1, locale => 'de'); # all three
render('greeting.tt', locale => 'de'); # ERROR: 'locale' becomes $cache
# then 'de' is the lone slurp arg
# (odd-length hash) - diagnose carefully
Αυτή η τελευταία περίπτωση είναι η παγίδα: μια προαιρετική παράμετρος κατά θέση ακολουθούμενη από slurpy hash είναι αμφίσημη σε κλήσεις μόνο-ονομαστικών-ορισμάτων. Είτε αφαιρέστε την προαιρετική κατά θέση και βάλτε τα πάντα στο hash, είτε περνάτε πάντα την προαιρετική κατά θέση ρητά.
Μετάβαση από αποσυσκευασία @_#
Η μηχανική μετάφραση:
# Before
sub make_user {
my ($name, $email, %extra) = @_;
...
}
# After
use feature 'signatures';
sub make_user ($name, $email, %extra) {
...
}
Αποκτάτε δωρεάν έλεγχο πληθικότητας και ονομαστικές λεξιλογικές. Το σώμα παραμένει αμετάβλητο.
Τα σημεία όπου δεν μπορείτε να μεταφράσετε μηχανικά:
Το σώμα χρησιμοποιεί δυναμικά τον αριθμό ορισμάτων (
if (@_ >= 3)) - οι υπογραφές καθορίζουν πληθικότητα κατά τον χρόνο ανάλυσης, οπότε αναδιαμορφώστε σε προαιρετική παράμετρο με προεπιλογή.Το σώμα τροποποιεί τo
$_[0]για το αποτέλεσμα ψευδωνυμοποίησης - κρατήστε την κλασική μορφή, καθώς οι υπογραφές εισάγουν αντίγραφα, σπάζοντας το ψευδώνυμο.The body uses
goto &otherand wants to forward the original@_-@_is still populated under signatures in 5.44, but this is implementation-defined and may change. Keep the classic form for tail-call forwarding.
Υπογραφές και πρωτότυπα είναι ορθογώνια#
Οι υπογραφές και τα πρωτότυπα λύνουν διαφορετικά προβλήματα:
Μηχανισμός | Επηρεάζει | Πότε ελέγχεται | Χρήσιμο για |
|---|---|---|---|
υπογραφή | η οπτική του σώματος | χρόνος εκτέλεσης | πληθικότητα, ονομαστικές παράμετροι |
prototype | πώς αναλύει ο αναλυτής | κατά τη μεταγλώττιση | ομοιώματα DSL |
Μια sub μπορεί να έχει και τα δύο, με το πρωτότυπο γραμμένο ως γνώρισμα:
use feature 'signatures';
sub mygrep :prototype(&@) ($code, @list) {
grep { $code->($_) } @list;
}
mygrep { /foo/ } @items; # prototype lets us drop `sub`
# signature gives us $code and @list
Το πρωτότυπο διαμορφώνει το σημείο κλήσης· η υπογραφή διαμορφώνει το σώμα. Δεν αλληλοεπικαλύπτονται.
Ο σημαντικότερος λόγος μετάβασης#
Ανίχνευση κλήσεων λάθος πληθικότητας τη στιγμή που συμβαίνουν - όχι αρκετές γραμμές μετά, όταν τελικά κάνετε $y + 1 και προκαλείτε προειδοποίηση για τιμή undef. Οι υπογραφές μετατρέπουν μια κατηγορία λεπτών σφαλμάτων σε ξεκάθαρο μήνυμα σφάλματος.
Δείτε επίσης#
Ορίσματα και
@_- ο κλασικός μηχανισμός με τον οποίο συνυπάρχουν οι υπογραφές.Πρωτότυπα - διαφορετικός μηχανισμός, που συχνά μπερδεύεται με τις υπογραφές.
sub- η σελίδα perlfunc της δεσμευμένης λέξης.Δήλωση - πού βρίσκονται οι υπογραφές στη σύνταξη δήλωσης.
Εμβέλεια - οι παράμετροι υπογραφής είναι λεξιλογικές τύπου
my.