סקלרים#
סקלר הוא ערך היחידה של Perl. הוא מחזיק אחד מן: מספר (מספר שלם או נקודה צפה), מחרוזת, הפניה, או undef. ה־sigil הוא $, בכל מיקום שבו הערך הוא סקלר יחיד - כולל כאשר הערך הוא אלמנט אחד של מערך או האש:
$x # the scalar named x
$arr[0] # the first element of @arr - also a scalar
$h{key} # one value from %h - also a scalar
סקלר אינו בעל טיפוס סטטי. אותו משתנה יכול להחזיק מספר עכשיו ומחרוזת רגע לאחר מכן. Perl ממיר בין השניים בכל פעם שאופרטור דורש צורה אחת או אחרת; ראו מספרים ומחרוזות.
אמת, מוגדרוּת ו־undef#
שתי שאלות קשורות אך נבדלות לגבי סקלר:
defined $x # is there any value at all?
$x ? T : F # is the value true?
סקלר הוא שקר בהקשר בוליאני אם הוא אחד מן:
undef # the undefined value
0 # numeric zero
0.0 # also numeric zero
"" # empty string
"0" # the literal string "0"
כל השאר הוא אמת. שימו לב ש־"00", "0.0", "0 but true" ו־"0E0" כולם אמת - אלה מחרוזות לא־ריקות שאינן תואמות לליטרל "0". השניים האחרונים הם ניבים נפוצים עבור ”פונקציה זו הוחזרה בהצלחה אך לא היה דבר לספור“:
sub touch_files {
my $count = 0;
$count++ for grep { -e $_ && utime undef, undef, $_ } @_;
return $count || '0E0'; # true even on zero work, so callers
# can write `if (touch_files(...))`
}
defined הוא הדרך היחידה להבחין בין undef לבין ערכים שקריים־אך־מוגדרים. באג נפוץ:
if ($cache{$key}) { ... } # WRONG - false for empty/0/undef
if (exists $cache{$key}) { ... } # right - pure presence test
if (defined $cache{$key}) { ... } # right - value-not-undef test
השתמשו ב־defined כאשר הדבר היחיד שמעניין אתכם הוא ”האם יש כאן ערך כלשהו בכלל“; ב־exists עבור ”האם מפתח/אינדקס זה נמצא במכל“ (השניים נבדלים עבור מערכים דלילים ומפתחות שעברו delete).
טיפוסים דינמיים#
סקלר יכול לשנות צורה במהלך הריצה:
my $x = 42; # internally an integer
$x = "hello"; # now a string
$x = 3.14; # now a float
$x = \@items; # now a reference
רוב הקוד אינו צריך לעולם לחשוב על איזו צורה פנימית יש לסקלר כרגע. היוצאים מן הכלל הם ספריות סריאליזציית JSON שאכפת להן אם 1 הושם כמספר או כמחרוזת, ועוזרי האינטרוספקציה של Scalar::Util (looks_like_number, dualvar).
”Looks like a number“#
כאשר Perl ממיר מחרוזת למספר הוא עוצר בתו הראשון שאינו חלק מקידומת מספרית תקפה:
"42" + 1 # 43
"42abc" + 1 # 43 - leading digits parsed
"abc42" + 1 # 1 - no leading digits, treated as 0
" 42" + 1 # 43 - leading whitespace allowed
"4_2" + 1 # 5 - underscores in literals only, NOT in strings
"0x1F" + 1 # 1 - hex string is NOT auto-recognised; hex() does
אי־ההתאמה בין ליטרלים מספריים (המכבדים _ ו־0x) לבין מחרוזות מספריות (שאינן מכבדות) היא אחת משאלות ה־“why“ המדווחות ביותר ב־Perl. השתמשו ב־hex / oct כאשר הקלט הוא מחרוזת בצורה לא־עשרונית:
my $bytes = hex "1F"; # 31
my $perms = oct "0755"; # 493
my $perms = oct "0o755"; # 493 - explicit octal prefix
my $bytes = oct "0x1F"; # 31 - oct() accepts any prefix
תחת use warnings, פעולת חשבון על מחרוזת לא־מספרית פולטת Argument ”…“ isn’t numeric in addition (+). הפעולה עדיין מחזירה 0 - האזהרה, לא שגיאה קטלנית, היא האות.
ערכים כפולים#
חלק מהסקלרים נושאים צורת מחרוזת וצורת מספר בו־זמנית, הנבחרות לפי הקשר. הדוגמה הקלאסית היא $!:
$! # in string context: "Permission denied"
$! + 0 # in numeric context: 13
ניתן לבנות משלכם בעזרת Scalar::Util::dualvar:
use Scalar::Util qw(dualvar);
my $err = dualvar 13, 'Permission denied';
print "err is $err"; # "err is Permission denied"
print "err is " . ($err + 0); # "err is 13"
סקלרים כפולים הם כלי נישה. המקרה הנפוץ שבו אחד מהם חשוב הוא ה־errno של $!; פתח המילוט הכללי הוא עוזר dualvar.
”0 but true“#
מחרוזת הליטרל "0 but true" היא הניב הקנוני של Perl עבור ”פונקציה שהחזרה הרגילה שלה היא מונה, אך המונה הוא אפס והקריאה הצליחה“. היא אמת (לא־ריקה, לא־"0") אך שווה מספרית ל־0:
my $hits = "0 but true";
if ($hits) { print "succeeded\n"; } # prints
print $hits + 0; # 0
print "got $hits results\n"; # got 0 but true results
המהדר גם מזהה את "0 but true" ספציפית ומדלג על אזהרת ה־isn’t numeric שכל מחרוזת אחרת של ”0 followed by garbage“ הייתה פולטת.