אמיתיוּת#
לפני לוגיקה, הערכים שעליהם לוגיקה פועלת. ל־Perl אין טיפוס בוליאני ייעודי. כל סקלר הוא או אמת או שקר כאשר משתמשים בו בהקשר בוליאני, והכלל קצר:
סקלר הוא שקר אם הוא אחד מארבעת הערכים
undef, המספר השלם0, המחרוזת"", או המחרוזת"0". כל דבר אחר הוא אמת.
ארבעה ערכי שקר, כל סקלר אחר — לרבות המחרוזות "00", "0.0", "0E0", ו־"false" — הוא אמת.
if (0) { ... } # false -- the integer zero
if (0.0) { ... } # false -- numerically zero
if ("") { ... } # false -- empty string
if ("0") { ... } # false -- the string "0"
if (undef) { ... } # false -- undefined value
if ("00") { ... } # TRUE -- non-empty, not the string "0"
if ("0.0") { ... } # TRUE -- non-empty, not the string "0"
if ("0 but true") { ... } # TRUE -- non-empty, not the string "0"
if (" ") { ... } # TRUE -- single space is non-empty
if ("false") { ... } # TRUE -- it's just a 5-character string
הניב "0 but true" אינו בדיחה. חלק מממשקי ה־API של Perl מחזירים ערך שחייב להשוות שווה לאפס מספרית (כך שבדיקה אריתמטית עושה את הדבר הנכון) אך להיות אמת בהקשר בוליאני. המקרה הקלאסי הוא ioctl() — הצלחה המחזירה אפס מילולי הייתה נבדקת כשקר. המחרוזת "0 but true" היא אפס מספרית (עם אזהרה המודחקת בהסכמה היסטורית) ובוליאנית־אמת מכיוון שאינה בקבוצת השקר בעלת ארבעת האיברים.
my $rc = ioctl($fh, $cmd, $buf);
$rc == 0 and warn "numeric zero"; # would fire on success
$rc or warn "boolean false"; # FIRES if API returned 0
# but NOT if "0 but true"
שני סוגים של השוואה#
ל־Perl יש משפחות מקבילות של אופרטורי השוואה מפני שיש לה תפיסות מקבילות של שוויון. מספרים מושווים מספרית; מחרוזות מושוות לקסיקוגרפית. המשפחה הלא־נכונה על הטיפוס הלא־נכון היא אחד הבאגים השכיחים ביותר ב־Perl למתחילים.
בדיקה | מספרי | מחרוזת |
|---|---|---|
שווה |
|
|
לא שווה |
|
|
קטן מ |
|
|
גדול מ |
|
|
קטן או שווה |
|
|
גדול או שווה |
|
|
תלת־כיווני (sort) |
|
|
== על מחרוזות מצליח תמיד עבור כל שתי מחרוזות לא־מספריות — שתיהן מומרות ל־0, ו־0 == 0 הוא אמת:
"foo" == "bar"; # TRUE -- both stringify to numeric 0
"foo" eq "bar"; # FALSE -- the actual question
"10" eq 10; # TRUE -- string "10" equals numeric 10 stringified
"10" == 10; # TRUE -- 10 == 10 numerically
"10" lt "9"; # TRUE -- lexical: "1" < "9"
"10" < "9"; # FALSE -- numeric: 10 > 9
<=> ו־cmp מחזירים -1, 0, או +1 — הצורה הסטנדרטית של מנגנון השוואה למיון. אלה אינם אופרטורים בוליאניים במובן המחמיר, אך הם מופיעים בהקשרים בוליאניים לעיתים מספיק קרובות שכדאי להכיר אותם.
מדוע זה חשוב ללוגיקה#
כל אופרטור בוליאני ב־Perl — &&, ||, //, !, xor, and, or, not — משתמש בקבוצת השקר בעלת ארבעת הערכים שלעיל ככלל הקלט שלו. בכל פעם שפרק להלן אומר ״אם $x הוא שקר״, זו בדיוק המשמעות: $x הוא undef, 0, "", או "0". בכל פעם שהוא אומר ״אם $x הוא אמת״, $x הוא כל דבר אחר.
שתי השלכות שכדאי לזכור:
סקלר יכול להיות אמת מבלי להיות ערך־אמת בוליאני. מחרוזות, הפניות, עצמים שעברו bless, מספרים גדולים — כולם אמת. כאשר אתם שואלים ״האם זה אמת?״ אינכם שואלים ״האם זה שווה ל־1?״ — אתם שואלים ״האם זה לא בקבוצת השקר?״.
התוצאה של אופרטור בוליאני אינה תמיד 1 או 0. הפרק הבא מכסה זאת בפירוט. בקצרה:
&&ו־||מחזירים אחד מ־האופרנדים שלהם, לא ערך בוליאני מנורמל. זוהי תכונה, לא תופעת לוואי, וניבים רבים של Perl תלויים בה.
ראו גם#
perlop — השוואה מספרית ו־השוואת מחרוזות — דפי מדריך העיון עבור
==/eqושאר משפחות ההשוואה שהוצגו לעיל.