שונות

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 בצד השמאלי של השמת רשימה הוא placeholder שמשליך את הערך התואם:

my ($x, undef, $z) = foo();         # discard the middle value
my (undef, @rest)  = @_;            # drop the first arg, keep the rest

ניב select קלאסי ל־sleep תת־שנייה - שלוש קבוצות מטפלי קובץ שמתעלמים מהן בתוספת timeout:

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, הוא אינו מקצר את המערך.

  • על משתנים קשורים וערכי DBM, undef $tied{$key} מפעיל את ה־STORE של ה־tie, לא את ה־DELETE שלו. אזהרת ה־perldoc (״probably not do what you expect on most predefined variables or DBM list values״) היא ספציפית על כך.

  • 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