הצהרה על Enum
enum מצהיר על טיפוס שהערכים שלו הם קבוצה קבועה של וריאנטים בעלי שם:
enum Status {
ready,
failed,
}
עכשיו Status הוא טיפוס עם בדיוק שני ערכים: Status.ready ו-Status.failed. שום דבר אחר לא יכול להיות Status.
הדקדוק קטן בכוונה:
enum Name {פותח את ההצהרה.- כל שורה מציינת שם של וריאנט אחד, מופרד בפסיק.
}סוגר אותה.
אין מטענים, אין ערכי מבחין, אין מתודות נגזרות: זה מה ששומר על enum בתור "טיפוס הסכום הקטן" ב-Zero.
שימוש ב-Enum
מציינים וריאנט על ידי הקדמת שם טיפוס ה-enum:
let state: Status = Status.ready
ההערה : Status אופציונלית ברגע שהביטוי שאחרי סימן השוויון קובע את הטיפוס; ברוב המקרים אפשר לכתוב:
let state = Status.ready
והקומפיילר יסיק שהטיפוס הוא Status.
השוואת ערכי Enum
שני ערכי enum שווים כשהם אותו וריאנט:
if state == Status.ready {
check world.out.write("ready\n")
} else {
check world.out.write("not ready\n")
}
זו הדרך הפשוטה ביותר לפצל לפי enum. לניתוח ממצה, כלומר טיפול מפורש בכל וריאנט, השתמשו ב-match:
match state {
.ready => { check world.out.write("ready\n") }
.failed => { check world.out.write("failed\n") }
}
היתרונות של match על פני if/else if מתגלים כשמוסיפים בהמשך וריאנט שלישי. הקומפיילר יראה לכם כל match שחסר בו המקרה החדש; שרשרת if/else פשוט תמשיך בשקט לענף ברירת המחדל שלה.
Choice ו-match מסביר את match בפירוט רב יותר. הוא עובד גם עבור enum וגם עבור choice.
דוגמה מלאה
הדוגמה הרשמית של Zero מציבה את enum ואת choice זה לצד זה באותו קובץ:
Status לא עושה כלום בקטע הזה: הוא שם כדי להראות את הניגוד. וריאנט של choice קושר מטען (value, message) בזמן ההתאמה; וריאנט של enum לא קושר כלום, כי אין מה לקשור.
Enum מול Choice: עץ החלטה קצר
כלל קצר:
- הוריאנטים הם רק תוויות →
enum. - הוריאנטים צריכים לשאת נתונים →
choice.
אם אתם ממדלים מצבים במחזור חיים ובשלב מסוים צריך לצרף הודעת שגיאה למצב "failed", החליפו את הטיפוס מ-enum ל-choice. כל וריאנט מקבל טיפוס מטען, וזרועות match בהמשך הקוד מקבלות קישור עבור המטען הזה. זה ריפקטורינג שהקומפיילר מוביל אתכם בו צעד אחר צעד.
באופן מוחשי:
// לפני: enum, בלי מטענים
enum Status {
ready,
failed,
}
// אחרי: choice עם מטען לכל וריאנט
choice Status {
ready: Void,
failed: String,
}
הוריאנטים שהמטען שלהם הוא Void הם פשוט תוויות בצורת choice. אפשר להשתמש ב-enum וב-choice לאותם מצבים לוגיים; בחרו ב-enum כשבאמת לא צריך לצרף נתונים.
מקרי שימוש
כמה דוגמאות יומיומיות שבהן enum הוא התשובה הנכונה:
- מחזור חיים בלי מטא-דאטה.
Loading,Ready,Empty: מצבים טהורים, בלי מטענים. - מצבי פעולה.
Read,Write,Appendעבור מצב פתיחת קובץ. - כיוון.
North,South,East,West. - רמת לוג.
Trace,Debug,Info,Warn,Error. (ייתכן שבהמשך תוסיפו הודעה, ואז תעברו ל-choice.) - יום בשבוע. דוגמה קלאסית.
בכל פעם שהייתם משתמשים אחרת בקבוע מספרי קסום (0 = ממתין, 1 = פעיל, 2 = הסתיים), enum כמעט תמיד ברור יותר.
הערות סגנון
- שמות וריאנטים באותיות קטנות תואמים את הסגנון של Zero למזהים בכל שאר השפה.
- פסיק אחרי הוריאנט האחרון הוא בסדר (ואף מומלץ כדי שה-diff יהיה נקי: הוספת וריאנט חדש לא משנה את השורה הקודמת).
- שמרו על רשימות enum קצרות. אם יש לכם תריסר וריאנטים ורבים מהם רוצים מטען, כנראה שאתם צריכים
choice, או עיצוב מחדש, ולאenumגדול יותר.
הבא בתור: Choice ו-Match
הצעד הטבעי הבא הוא בן הדוד העשיר יותר: choice ו-match, טיפוס האיחוד המתויג של Zero ומבנה התאמת התבניות שמגיע איתו.
שאלות נפוצות
מה זה enum ב-Zero?
enum מצהיר על טיפוס שהערכים שלו הם אחד מתוך קבוצה קבועה של וריאנטים בעלי שם: תוויות בלי מטען נוסף. דוגמה: enum Status { ready, failed }. ערך מטיפוס Status הוא בדיוק אחד מבין Status.ready או Status.failed, והקומפיילר אוכף את זה.
במה enum שונה מ-choice?
הוריאנטים של enum הם תוויות פשוטות: הם לא נושאים נתונים. choice הוא איחוד מתויג: לכל וריאנט יש טיפוס מטען משויך, כמו choice Result { ok: i32, err: String }. השתמשו ב-enum כשצריך רק להבחין בין מקרים לפי שם; השתמשו ב-choice כשכל מקרה נושא מידע נוסף.
איך בודקים איזה וריאנט של enum יש לערך?
משווים את הערך לוריאנט: if status == Status.ready { ... }. לפיצול ממצה על כל הוריאנטים, השתמשו ב-match: הקומפיילר יתריע אם פספסתם וריאנט, וזו הסיבה העיקרית להעדיף match על פני שרשראות if/else if כשהערך הוא טיפוס סכום.
האם לוריאנטים של enum יכולים להיות ערכים משויכים ב-Zero?
לא, לשם כך יש את choice. enum הוא בכוונה טיפוס הסכום המינימלי: כל וריאנט הוא רק תווית. אם צריך לצרף i32 או String לאחד הוריאנטים, enum כבר לא מספיק ואתם צריכים choice.
מתי כדאי להשתמש ב-enum ב-Zero?
השתמשו ב-enum כשערך חייב להיות בדיוק אחד מתוך קבוצה קטנה של מצבים בעלי שם, והמצבים האלה לא נושאים נתונים נוספים. דוגמאות: יום בשבוע, צבע של רמזור, מצב במחזור חיים בלי מטא-דאטה, רמת לוג. אם אתם מוצאים את עצמכם רוצים לצרף נתונים לאחד הוריאנטים, עברו ל-choice.