Διάφορα

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;»· ο φυσικός αντίστοιχος της τιμής undef

  • delete - αφαιρέστε κλειδί πίνακα κατακερματισμού ή στοιχείο πίνακα εξ ολοκλήρου· χρησιμοποιήστε αυτή, όχι την undef, όταν θέλετε η exists να γίνει ψευδής

  • exists - ελέγξτε αν κλειδί πίνακα κατακερματισμού ή ευρετήριο πίνακα είναι παρόν, ανεξάρτητα αν η τιμή του είναι ορισμένη

  • local - αντικαθιστά προσωρινά την τιμή μιας μεταβλητής πακέτου (συχνά με undef) για τη διάρκεια μιας εμβέλειας

  • wantarray - συνδυάζεται με την undef στο ιδιωματικό wantarray ? (undef, $err) : undef για επιστροφή αποτυχίας διπλού περιβάλλοντος