undef#
Η απροσδιόριστη τιμή, και ο τελεστής που την παράγει.
Η undef φοράει δύο καπέλα. Η σκέτη undef είναι τιμή - το κανονικό απροσδιόριστο βαθμωτό, αυτό για το οποίο η defined επιστρέφει ψευδές. Η undef EXPR είναι μοναδιαίος τελεστής που απροσδιοριστοποιεί το όρισμά της επιτόπια: η μεταβλητή, πίνακας, πίνακας κατακερματισμού, υπορουτίνα ή typeglob που κατονομάζει η EXPR αδειάζεται και, όπου είναι δυνατόν, απελευθερώνεται η αποθήκευσή του.
Και οι δύο μορφές αποτιμώνται στην απροσδιόριστη τιμή.
Σύνοψη#
undef # the undefined value
undef EXPR # undefine the lvalue EXPR, return undef
Η EXPR πρέπει να είναι lvalue: βαθμωτό, πίνακας (με @), πίνακας κατακερματισμού (με %), υπορουτίνα (με &) ή typeglob (με *).
Τι επιστρέφεται#
Πάντα η απροσδιόριστη τιμή. Η μορφή τελεστή επιστρέφει undef μετά το σβήσιμο του ορίσματός της· η μορφή τιμής απλώς σας δίνει undef.
my $x = undef; # $x is now undef
return undef if $oops; # explicit "I mean no value"
my $was = undef $counter; # $counter wiped, $was is undef
Η τιμή έναντι του τελεστή#
Η σκέτη undef είναι το απροσδιόριστο βαθμωτό. Η ανάθεσή της σε μεταβλητή αφήνει την αποθήκευση της μεταβλητής στη θέση της και θέτει την τιμή της σε undef:
my @big = (1) x 1_000_000;
$big[0] = undef; # slot 0 holds undef; @big still huge
@big = (); # empties the array, keeps the AV
@big = undef; # assigns the ONE-element list (undef)
Σημειώστε την τελευταία γραμμή: η @big = undef είναι ανάθεση λίστας μίας λίστας ενός στοιχείου του οποίου το μοναδικό στοιχείο είναι undef, οπότε ο @big καταλήγει με μήκος 1. Σχεδόν ποτέ δεν είναι αυτό που θέλετε. Χρησιμοποιήστε @big = () για άδειασμα, ή undef @big για άδειασμα και απελευθέρωση της υποκείμενης αποθήκευσης.
Η μορφή τελεστή κάνει περισσότερα από το να αναθέτει undef:
undef $scalar; # scalar: sets value to undef, frees any PV buffer
undef @array; # array: frees all elements AND the AV's storage
undef %hash; # hash: frees all entries AND the HV's buckets
undef ⊂ # sub: frees the CV body; the name still exists
undef *glob; # glob: destroys $glob, @glob, %glob, &glob, etc.
Η διάκριση έχει σημασία για τη μνήμη. Η @array = () αφήνει την κατανεμημένη χωρητικότητα ανέπαφη ώστε το επόμενο push να είναι φθηνό· η undef @array την απελευθερώνει. Για μεγάλο, εφάπαξ πίνακα που θέλετε να αφήσετε πραγματικά, χρησιμοποιήστε undef. Για πίνακα εργασίας που θα γεμίσετε ξανά, χρησιμοποιήστε = ().
Παραδείγματα#
Επιστροφή «καμίας τιμής» από υπορουτίνα. Σε βαθμωτό περιβάλλον αυτός είναι ένας καθαρός τρόπος να σηματοδοτήσετε αποτυχία· σε περιβάλλον λίστας η σκέτη undef παράγει λίστα ενός στοιχείου που περιέχει undef, η οποία είναι αληθής:
sub find_user {
my ($id) = @_;
return undef unless $id; # scalar-context caller: false
...
}
Για υπορουτίνες που προορίζονται να σηματοδοτούν αποτυχία και στα δύο περιβάλλοντα, επιστρέψτε αντ” αυτού κενή λίστα - η return χωρίς όρισμα κάνει το σωστό:
sub find_user {
my ($id) = @_;
return unless $id; # () in list ctx, undef in scalar ctx
...
}
Παράκαμψη θεσιακών τιμών σε ανάθεση λίστας. Η undef στην αριστερή πλευρά μιας ανάθεσης λίστας είναι σύμβολο κράτησης θέσης που πετάει την αντίστοιχη τιμή:
my ($x, undef, $z) = foo(); # discard the middle value
my (undef, @rest) = @_; # drop the first arg, keep the rest
Κλασικό ιδίωμα select για ύπνο κάτω του δευτερολέπτου - τρία αγνοημένα σύνολα filehandle συν χρονικό όριο:
select undef, undef, undef, 0.25; # sleep 250 ms
Επιστροφή διπλού περιβάλλοντος:
return wantarray ? (undef, $errmsg) : undef if $they_blew_it;
Απελευθέρωση μεγάλου συνόλου εργασίας:
my %cache = build_huge_cache();
use_cache(\%cache);
undef %cache; # free buckets and entries now
Απροσδιοριστοποίηση υπορουτίνας. Το όνομα στον πίνακα συμβόλων παραμένει, αλλά η κλήση της θα παραπονεθεί για απροσδιόριστη υπορουτίνα:
sub greet { print "hi\n" }
undef &greet;
greet(); # Undefined subroutine &main::greet
Η απροσδιοριστοποίηση typeglob εκμηδενίζει κάθε υποδοχή ταυτόχρονα:
our $xyz = 1;
our @xyz = (1, 2);
our %xyz = (a => 1);
sub xyz { 42 }
undef *xyz; # $xyz, @xyz, %xyz, &xyz all gone
Οριακές περιπτώσεις#
Η
undef $hash{$key}δεν είναιdelete. Θέτει την τιμή σε εκείνο το κλειδί σε undef· το ίδιο το κλειδί εξακολουθεί να υπάρχει και ηexistsεξακολουθεί να επιστρέφει αληθές. Χρησιμοποιήστεdelete $hash{$key}για να αφαιρέσετε το κλειδί. Το ίδιο ισχύει για τα στοιχεία πίνακα: ηundef $arr[3]αφήνει το ευρετήριο 3 στη θέση του με τιμή undef, δεν συντομεύει τον πίνακα.Σε tied μεταβλητές και τιμές DBM, η
undef $tied{$key}καλεί τοSTOREτης tie, όχι τοDELETEτης. Η προειδοποίηση του perldoc («πιθανότατα δεν κάνει αυτό που περιμένετε στις περισσότερες προκαθορισμένες μεταβλητές ή τιμές λίστας DBM») αφορά συγκεκριμένα αυτό.Η
undefείναι μοναδιαίος τελεστής, όχι τελεστής λίστας. Παίρνει ακριβώς ένα όρισμα, οπότε ηundef $a, $bαναλύεται ως(undef $a), $b- μόνο η$aαπροσδιοριστοποιείται. Για να απροσδιοριστοποιήσετε πολλές μεταβλητές, καλέστε την αρκετές φορές, ή χρησιμοποιήστε βρόχο:undef $_ for $a, $b, $c;
Η
undef EXPRαπαιτεί lvalue. Οιundef 42ήundef func()είναι σφάλμα μεταγλώττισης (Can’t modify … in undef operator).Η
undefστην αριστερή πλευρά σε ανάθεση λίστας είναι σύνταξη, όχι τιμή. Η(undef, $x) = @pairαναλύεται ειδικά· δεν μπορείτε να γράψετεmy $slot = undef; ($slot, $x) = @pairκαι να περιμένετε η πρώτη τιμή να απορριφθεί - αυτό κάνει ανάθεση στο$slot.Η σταθερή
undefσε λογικό περιβάλλον είναι ψευδής, σε αριθμητικό περιβάλλον είναι0, σε περιβάλλον συμβολοσειράς είναι"". Υπόuse warningsκαθεμία από αυτές τις μετατροπές εκπέμπει προειδοποίησηUse of uninitialized valueστο σημείο χρήσης, όχι στο σημείο που η μεταβλητή έγινε undef.Η
undef &subδεν αφαιρεί το όνομα της υπορουτίνας από το stash του πακέτου της - μόνο τον κώδικα. Για να αφαιρέσετε και το όνομα, απροσδιοριστοποιήστε ολόκληρη την υποδοχή glob:delete $Package::{sub_name}ήundef *Package::sub_nameαν θέλετε επίσης να φύγουν οι αδελφές υποδοχές.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
defined- το κατηγόρημα που ρωτάει «είναι αυτή η τιμή μη-undef;»· ο φυσικός αντίστοιχος της τιμήςundefdelete- αφαιρέστε κλειδί πίνακα κατακερματισμού ή στοιχείο πίνακα εξ ολοκλήρου· χρησιμοποιήστε αυτή, όχι τηνundef, όταν θέλετε ηexistsνα γίνει ψευδήςexists- ελέγξτε αν κλειδί πίνακα κατακερματισμού ή ευρετήριο πίνακα είναι παρόν, ανεξάρτητα αν η τιμή του είναι ορισμένηlocal- αντικαθιστά προσωρινά την τιμή μιας μεταβλητής πακέτου (συχνά μεundef) για τη διάρκεια μιας εμβέλειαςwantarray- συνδυάζεται με τηνundefστο ιδιωματικόwantarray ? (undef, $err) : undefγια επιστροφή αποτυχίας διπλού περιβάλλοντος