Υπογραφές#
Μια υπογραφή είναι μια λίστα παραμέτρων σε παρενθέσεις που τοποθετείται αμέσως μετά το όνομα της sub (και μετά τα γνωρίσματα), στη θέση - ή επιπλέον - της χειροκίνητης αποσυσκευασίας @_ του σώματος. Οι υπογραφές εισάγουν λεξιλογικές μεταβλητές παραμέτρων, εκτελούν έλεγχο πληθικότητας κατά τον χρόνο κλήσης, και υποστηρίζουν προεπιλεγμένες τιμές και slurpy παραμέτρους.
Οι υπογραφές σταθεροποιήθηκαν στην Perl 5.36· στην 5.42 είναι χαρακτηριστικό παραγωγής διαθέσιμο με ένα από τα:
use feature 'signatures'; # explicit feature import
use v5.36; # implicit (signatures + other 5.36 features)
Η PetaPerl υποστηρίζει πλήρως τη σύνταξη υπογραφών της 5.42.
Βασική μορφή#
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]για το αποτέλεσμα ψευδωνυμοποίησης - κρατήστε την κλασική μορφή, καθώς οι υπογραφές εισάγουν αντίγραφα, σπάζοντας το ψευδώνυμο.Το σώμα χρησιμοποιεί
goto &otherκαι θέλει να προωθήσει το αρχικό@_- το@_εξακολουθεί να γεμίζεται υπό υπογραφές στην 5.42, αλλά αυτό ορίζεται από την υλοποίηση και μπορεί να αλλάξει. Κρατήστε την κλασική μορφή για προώθηση κλήσης ουράς.
Υπογραφές και πρωτότυπα είναι ορθογώνια#
Οι υπογραφές και τα πρωτότυπα λύνουν διαφορετικά προβλήματα:
Μηχανισμός | Επηρεάζει | Πότε ελέγχεται | Χρήσιμο για |
|---|---|---|---|
υπογραφή | η οπτική του σώματος | χρόνος εκτέλεσης | πληθικότητα, ονομαστικές παράμετροι |
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.