defined#
Έλεγχος εάν μια τιμή, μεταβλητή ή υπορουτίνα είναι ορισμένη.
Η defined επιστρέφει αληθές όταν η EXPR κρατά οποιαδήποτε τιμή εκτός της απροσδιόριστης τιμής undef, και ψευδές όταν κρατά undef. Είναι ο μοναδικός τρόπος να διακρίνεις την undef από τις άλλες ψευδείς τιμές (0, "", "0"), κάτι που ένας απλός λογικός έλεγχος δεν μπορεί.
Σύνοψη#
defined EXPR
defined
defined &SUBROUTINE
Τι επιστρέφεται#
Μια λογική τιμή: αληθές αν η EXPR είναι ορισμένη, ψευδές αν είναι undef.
Χωρίς όρισμα, η defined λειτουργεί στην $_.
Το αποτέλεσμα είναι ευαίσθητο στο περιβάλλον μόνο με τη συνήθη λογική έννοια· η defined δεν διαδίδει περιβάλλον λίστας στην EXPR.
Γιατί υπάρχει, και γιατί ένας απλός λογικός έλεγχος δεν αρκεί#
Πολλές λειτουργίες επιστρέφουν undef για να σηματοδοτήσουν αποτυχία, τέλος αρχείου, σφάλμα συστήματος, μη αρχικοποιημένη μεταβλητή ή κάποια άλλη εξαιρετική συνθήκη. Η defined σας επιτρέπει να διακρίνετε αυτή τη φρουρά από ένα νόμιμο αποτέλεσμα. Ένας απλός λογικός έλεγχος αντιμετωπίζει τα undef, 0, "" και "0" όμοια - και τα τέσσερα είναι ψευδή - οπότε δεν μπορείτε να χρησιμοποιήσετε την αληθοτιμία για να διακρίνετε «τίποτα δεν επιστράφηκε» από «επιστράφηκε μηδέν»:
my $n = some_count();
if ($n) { ... } # false for 0 AND for undef
if (defined $n) { ... } # false only for undef
Σημειώστε ότι η undef είναι η ίδια έγκυρη βαθμωτή τιμή. Η παρουσία της δεν σημαίνει απαραίτητα ότι κάτι πήγε στραβά: η pop @empty επιστρέφει undef, αλλά το ίδιο κάνει και η pop @array όταν το στοιχείο που απομακρύνθηκε ήταν το ίδιο undef. Η defined σας λέει ότι η τιμή είναι undef· δεν σας λέει γιατί.
Προεπιλεγμένο όρισμα: $_#
Χωρίς όρισμα, η defined ελέγχει την $_:
while (<$fh>) {
next unless defined; # same as: defined $_
chomp;
...
}
defined &subroutine#
Η defined &func ρωτά αν η υπορουτίνα func έχει οριστεί ποτέ. Μια προδήλωση (sub func;) δεν την κάνει ορισμένη· ένα πραγματικό σώμα την κάνει:
sub greet { "hello" }
print defined &greet ? "yes\n" : "no\n"; # yes
print defined &missing ? "yes\n" : "no\n"; # no
Μια υπορουτίνα που δεν είναι ορισμένη μπορεί παρ” όλα αυτά να είναι καλέσιμη: η μέθοδος AUTOLOAD του πακέτου μπορεί να την δημιουργήσει στην πρώτη κλήση. Η defined &func αντικατοπτρίζει την τρέχουσα κατάσταση του πίνακα συμβόλων, όχι το τι μπορεί να παραγάγει ένα μελλοντικό AUTOLOAD. Δείτε το perlsub.
Η τιμή επιστροφής δεν επηρεάζεται από προδηλώσεις.
Στοιχεία πίνακα κατακερματισμού: defined έναντι exists#
Σε ένα στοιχείο πίνακα κατακερματισμού, η defined ρωτά για την τιμή, όχι το κλειδί:
my %h = (a => 1, b => undef);
print exists $h{a} ? 1 : 0, "\n"; # 1
print defined $h{a} ? 1 : 0, "\n"; # 1
print exists $h{b} ? 1 : 0, "\n"; # 1 - key is present
print defined $h{b} ? 1 : 0, "\n"; # 0 - value is undef
print exists $h{c} ? 1 : 0, "\n"; # 0 - key not present
print defined $h{c} ? 1 : 0, "\n"; # 0 - also autovivifies? no, rvalue is safe
Χρησιμοποιήστε την exists για να ρωτήσετε «βρίσκεται αυτό το κλειδί στον πίνακα κατακερματισμού;» και την defined για να ρωτήσετε «κρατά αυτή η θέση μια χρησιμοποιήσιμη τιμή;». Οι δύο διαφέρουν όποτε μια τιμή έχει εκχωρηθεί ρητά ως undef ή έχει αφεθεί undef εκ κατασκευής (π.χ. $h{b} = undef, ή @h{qw(a b c)} = (1)).
Η ίδια διάκριση ισχύει για τα στοιχεία πίνακα: η exists $a[7] αναφέρει αν ο πίνακας είναι αρκετά μεγάλος και η θέση έχει εκχωρηθεί, ενώ η defined $a[7] αναφέρει αν αυτή η θέση κρατά αυτή τη στιγμή μη-undef τιμή.
Παραδείγματα#
Το κοινό ιδίωμα pop-μέχρι-άδειασμα - σταματά μόνο όταν ο πίνακας εξαντληθεί, όχι σε νόμιμο ψευδές στοιχείο:
while (defined(my $val = pop @ary)) {
process($val);
}
Έλεγχος κλήσης συστήματος για αποτυχία:
my $target = readlink $sym;
die "can't readlink $sym: $!" unless defined $target;
Κλήση ενός coderef μόνο αν παρασχέθηκε ένα:
sub dispatch {
my ($cb, @args) = @_;
return defined &$cb ? $cb->(@args) : die "no callback";
}
Παροχή προεπιλογής χωρίς να καταστρέφεται νόμιμο 0 ή "":
$debugging = 0 unless defined $debugging;
Η σύγχρονη μορφή είναι ο τελεστής defined-or //, ο οποίος εκτελεί ακριβώς αυτόν τον έλεγχο ενσωματωμένα:
$debugging //= 0;
my $name = $user // "anonymous";
Σύλληψη regex: το ότι η $1 είναι ορισμένη σας λέει ότι η ομάδα σύλληψης συμμετείχε στην αντιστοιχία, ακόμη και αν ταίριαξε με την κενή συμβολοσειρά:
"ab" =~ /a(.*)b/;
print defined $1 ? "matched '$1'\n" : "no match\n"; # matched ''
Συγκεντρώσεις: τα defined @array, defined %hash δεν υποστηρίζονται πλέον#
Παλαιότερα τα defined @array και defined %hash ανέφεραν αν είχε ποτέ δεσμευτεί μνήμη για τη συγκέντρωση - μια λεπτομέρεια υλοποίησης που σπάνια ήταν αυτό που οι καλούντες πραγματικά ήθελαν. Η σύγχρονη Perl απορρίπτει αυτές τις μορφές. Ελέγξτε το μέγεθος της συγκέντρωσης αντί αυτού:
if (@array) { print "array has elements\n" }
if (%hash) { print "hash has members\n" }
Σε λογικό περιβάλλον ένας πίνακας αποτιμάται στο πλήθος των στοιχείων του και ένας πίνακας κατακερματισμού αποτιμάται σε αληθή τιμή αν και μόνο αν έχει κλειδιά. Αυτός είναι ο έλεγχος που σχεδόν πάντα θέλατε.
Ο έλεγχος ενός στοιχείου μιας συγκέντρωσης παραμένει αποδεκτός και είναι η συνήθης χρήση: defined $array[$i], defined $hash{$key}.
Υπερβολική χρήση#
Η defined χρησιμοποιείται συχνά υπερβολικά. Το μηδέν και η κενή συμβολοσειρά είναι ορισμένες τιμές. Μια αντιστοιχία regex που συλλαμβάνει μηδέν χαρακτήρες θέτει παρ” όλα αυτά την $1 σε ορισμένη κενή συμβολοσειρά - η αντιστοιχία δεν απέτυχε· ταίριαξε κάτι που έτυχε να έχει μήκος μηδέν. Όταν μια συνάρτηση επιστρέφει undef, παραδέχεται ότι δεν μπορεί να σας δώσει ουσιαστική απάντηση. Καταφεύγετε στην defined όταν αμφισβητείτε την ακεραιότητα μιας τιμής. Για «είναι μηδέν;» ή «είναι κενό;» μια απλή σύγκριση με 0 ή "" είναι αυτό που χρειάζεστε.
Οριακές περιπτώσεις#
Σκέτη
definedχωρίς όρισμα ελέγχει την$_. Μέσα σεmap,grepή βρόχοwhile (<$fh>)αυτή είναι η ιδιωματική μορφή.defined(&func)έναντιdefined(&{$ref}): και τα δύο λειτουργούν. Το δεύτερο αποαναφέρει μια αναφορά κώδικα και ρωτά αν η θέση που αναφέρεται κρατά αυτή τη στιγμή ορισμένο σώμα υπορουτίνας.Η
defined $hash{$key}δεν αυτο-δημιουργεί το κλειδί - ηdefinedείναι περιβάλλον rvalue και αφήνει τον πίνακα κατακερματισμού αμετάβλητο. Αντιπαραβάλετε με το$hash{$key}{inner} = 1, το οποίο αυτο-δημιουργεί.Αλυσιδωτή πρόσβαση πίνακα κατακερματισμού/πίνακα: η
defined $h{a}{b}αυτο-δημιουργεί την$h{a}σε μια κενή αναφορά πίνακα κατακερματισμού για να εκτελέσει την εσωτερική αναζήτηση, ακόμη και αν η εξωτερικήdefinedδιαβάζει το αποτέλεσμα. Αυτή είναι συνέπεια του πώς αποτιμάται η αλυσίδα αποαναφοράς, όχι της ίδιας τηςdefined. Για να εξετάσετε εμφωλευμένη δομή χωρίς αυτο-δημιουργία, ελέγξτε κάθε επίπεδο πρώτα με τηνexists.defined $&,defined $1: μετά από επιτυχή αντιστοιχία αυτές είναι ορισμένες· μετά από αποτυχημένη αντιστοιχία διατηρούν όποια τιμή είχαν από την προηγούμενη επιτυχή αντιστοιχία στην ίδια εμβέλεια. Ηdefinedαπό μόνη της δεν είναι ασφαλής έλεγχος για «πέτυχε η αντιστοιχία;» - ελέγξτε την τιμή επιστροφής του τελεστή αντιστοίχισης αντί αυτού.Η
definedδεν είναι lvalue. Τοdefined $x = $yείναι συντακτικό σφάλμα· βάλτε την εκχώρηση σε παρενθέσεις:defined($x = $y).
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
undef- η τιμή έναντι της οποίας ελέγχει ηdefined, και ο τελεστής που την παράγει ή την καθαρίζειexists- ρωτά αν ένα κλειδί πίνακα κατακερματισμού ή δείκτης πίνακα είναι παρών, ανεξάρτητα από το αν η τιμή του είναιundefref- όταν το ερώτημα δεν είναι «είναι ορισμένο» αλλά «τι είδους αναφορά είναι αυτή»//και//=- τελεστής defined-or· η σύγχρονη ενσωματωμένη μορφή τουdefined($x) ? $x : $default$_- το προεπιλεγμένο όρισμα όταν ηdefinedκαλείται χωρίς έκφραση