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 //, אשר מבצע בדיוק את הבדיקה הזו inline:
$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}): שניהם עובדים. השני מבצע dereference להפניית קוד ושואל האם החריץ המופנה מחזיק כעת גוף תת־שגרה מוגדר.defined $hash{$key}אינו מבצע autovivify למפתח -definedהוא הקשר rvalue ומשאיר את ההאש ללא שינוי. בניגוד ל־$hash{$key}{inner} = 1, שכן מבצע autovivify.גישת האש/מערך משורשרת:
defined $h{a}{b}מבצע autovivify ל־$h{a}להפניית האש ריקה כדי לבצע את החיפוש הפנימי, גם אם ה־definedהחיצוני קורא את התוצאה. זוהי תוצאה של אופן הערכת שרשרת ה־dereference, לא שלdefinedעצמו. כדי לבחון מבנה מקונן ללא autovivify, יש לבדוק כל רמה עםexistsקודם.defined $&,defined $1: לאחר התאמה מוצלחת אלה מוגדרים; לאחר התאמה כושלת הם שומרים את הערך שהיה להם מההתאמה המוצלחת הקודמת באותו תחום.definedבלבד אינו בדיקה בטוחה של ״האם ההתאמה הצליחה״ - יש לבדוק את ערך ההחזרה של אופרטור ההתאמה במקום.definedאינו lvalue.defined $x = $yהיא שגיאת תחביר; יש לעטוף את ההשמה בסוגריים:defined($x = $y).
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
undef- הערך ש־definedבודק כנגדו, והאופרטור שמייצר אותו או מנקה אותוexists- לשאול האם מפתח האש או אינדקס מערך נוכח, ללא תלות בכך שהערך שלו הואundefref- כאשר השאלה אינה ״האם זה מוגדר״ אלא ״איזה סוג הפניה זו״//and//=- אופרטור defined-or; הצורה המודרנית inline שלdefined($x) ? $x : $default$_- ארגומנט ברירת המחדל כאשרdefinedנקרא ללא ביטוי