Menu

If/Else ב-Zero: הסבר על הסתעפות מותנית

איך if ו-else עובדים ב-Zero: תנאים בוליאניים, גופי ענפים, היעדר כפייה ל-truthy, ואיך תנאים משתלבים לצד match להסתעפות עשירה יותר.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

היסודות

if ב-Zero נראה בערך כמו if בכל שפה אחרת ממשפחת C, עם הגבלה בולטת אחת: התנאי חייב להיות bool.

התנאי value == 42 הוא bool כי == בין שני ערכי i32 מחזיר bool. כל אחת משתי הזרועות מכילה בלוק של פקודות. אפשר פחות או יותר להשמיט זרוע, ה-else אופציונלי, אבל כששתיהן קיימות, שתיהן חייבות להיות בלוקים של { ... }.

הדרישה ל-bool

שפות מסוימות מאפשרות לכתוב if value { ... } ולהתייחס ל-0, ל-"" או ל-null כאל falsy. Zero לא. התנאי חייב להיות bool אמיתי.

let count = 0
if count {              // שגיאת קומפילציה: מצופה bool, התקבל i32
    // ...
}

if count == 0 {         // OK
    check world.out.write("nothing to do\n")
}

הסיבה זהה לזו שעוברת בכל שאר השפה: מפורש עדיף על מרומז. סוכן שקורא את הצורה השנייה יודע בדיוק מה נבדק. הצורה הראשונה משאירה את כללי ה-truthiness מרומזים, והם משתנים בין שפות: Zero בוחרת לוותר עליהם.

Else ו-Else-If

פסוקית else רצה כשהתנאי שקרי:

משרשרים תנאים עם else if:

if value < 0 {
    check world.out.write("negative\n")
} else if value == 0 {
    check world.out.write("zero\n")
} else {
    check world.out.write("positive\n")
}

else if הוא פשוט else { if ... } בלי הסוגריים המסולסלים: אותה סמנטיקה, פחות הזחה. ה-else האחרון אופציונלי.

מאיפה מגיע התנאי

התנאי יכול להיות כל דבר שמחושב ל-bool:

  • קישור מטיפוס bool: if ok { ... }.
  • השוואה: if value == 42 { ... }, if x < y { ... }.
  • צירוף לוגי: if a && b { ... }, if pair.left == 1_u8 && pair.right == 2_u8 { ... }.
  • קריאה לפונקציה שמחזירה bool: if isReady(world) { ... }.

קטע אמיתי מתוך הדוגמאות של השפה:

let pair: BytePair = Pair { left: 1_u8, right: 2_u8 }
if pair.left == 1_u8 && pair.right == 2_u8 {
    check world.out.write("type alias ok\n")
} else {
    check world.out.write("type alias broke\n")
}

&& מקצר את החישוב כמו שהייתם מצפים: אם האופרנד הראשון הוא false, האופרנד השני לא מחושב. אותו דבר עבור ||.

מתי להשתמש ב-match במקום

שרשראות if/else if מתאימות להחלטות של שניים או שלושה כיוונים, במיוחד כשלתנאים אין מבנה משותף. אבל כשמפצלים לפי הוריאנטים של טיפוס סכום, choice או enum, match הוא הכלי הנכון.

השוו:

// match: ממצה, נבדק על ידי הקומפיילר
match result {
    .ok  => value   { check world.out.write("ok\n") }
    .err => message { check world.out.write("err\n") }
}

לעומת:

// if/else על טיפוס סכום: ארוך יותר וקל יותר לטעות בו
if result.isOk() {
    let value = result.unwrap()
    check world.out.write("ok\n")
} else {
    check world.out.write("err\n")
}

הצורה של match הופכת את ניתוח הוריאנטים למפורש, והקומפיילר יתלונן אם יתווסף בהמשך וריאנט ותשכחו לטפל בו. הצורה של if מעבירה בשקט כל מה שאינו ok לענף ה-else, כולל וריאנטים חדשים לגמרי שמעולם לא חשבתם עליהם.

כלל אצבע: if לבוליאנים, match לוריאנטים.

הערות סגנון

כמה מוסכמות קטנות שהופכות קוד לקל יותר לקריאה, גם לבני אדם וגם לסוכנים:

  • תמיד עטפו את הגוף בסוגריים מסולסלים. גם גוף של שורה אחת נכנס ל-{ ... }. אין צורה של פקודה בודדת בלי סוגריים. זה מכוון: כך ההזחה נשארת אמינה, ומוסר מקור נפוץ לבאגים במשפחת C.
  • שימו את הענף הנפוץ ביותר ראשון. קוראים (וסוכנים) סורקים מלמעלה למטה.
  • העדיפו תנאים חיוביים כשהם ברורים באותה מידה. if isReady קל יותר למעקב מאשר if !notReady, כשכל השאר שווה.

הבא בתור: לולאות While

תנאים מחליטים מה לעשות; לולאות מחליטות כמה פעמים לעשות את זה. המסמך הבא מכסה את לולאות while של Zero, מבנה הלולאה של השלב המוקדם שהשפה מגיעה איתו.

שאלות נפוצות

איך משפטי if עובדים ב-Zero?

משתמשים ב-if condition { ... } עם פסוקית else { ... } אופציונלית. התנאי חייב להיות bool: Zero לא ממירה מספרים שלמים, מחרוזות או ערכים אחרים לבוליאני. דוגמה: if value == 42 { check world.out.write("yes\n") } else { check world.out.write("no\n") }.

האם יש ב-Zero אופרטור טרנרי?

Zero שומרת בכוונה על משטח קטן ומשתמשת בבלוקים של if / else במקום באופרטור טרנרי נפרד מהצורה condition ? a : b. הדוגמאות הרשמיות מעדיפות ענפים מפורשים גם במקרים קצרים. אם השפה שלכם תומכת ב-if כביטוי, צפו ש-Zero תנטה לכיוון הזה ולא תוסיף תחביר שני.

האם אפשר לשרשר if/else if ב-Zero?

כן. משרשרים תנאים על ידי כתיבת else if בין הענפים: if a { ... } else if b { ... } else { ... }. להסתעפות מורכבת יותר על choice או enum, השתמשו במקום זאת ב-match: הוא ממצה יותר, והקומפיילר בודק שטיפלתם בכל וריאנט.

למה Zero לא ממירה ערכים ל-bool?

פילוסופיית העיצוב של Zero היא 'הכול מפורש'. truthiness מרומזת, כלומר התייחסות ל-0, ל-"" או ל-null כאל false, היא מקור נפוץ לבאגים, וקשה לסוכן לחשוב עליה בדיוק. הדרישה ל-bool אמיתי הופכת את החלטת ההסתעפות לגלויה בקוד המקור וקלה יותר לאימות מכני.

מתי להשתמש ב-match במקום ב-if/else?

השתמשו ב-match כשאתם מפצלים לפי הוריאנטים של choice או enum. הקומפיילר יכול לוודא שכיסיתם כל מקרה, ושרשראות if/else if לא יכולות לעשות את זה. שמרו את if/else לפרדיקטים בוליאניים פשוטים: בדיקות שוויון, השוואות והסתעפויות קצרות לשני כיוונים.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל