כתבו את הקובץ
פתחו את העורך ושמרו את חמש השורות הבאות בשם hello.0 במקום נוח, או פשוט לחצו על Run בבלוק שלמטה:
זהו, תוכנית Zero שלמה. כדי להריץ אותה מקומית:
zero run hello.0
אתם אמורים לראות:
hello from zero
אם קיבלתם command not found, חזרו אל התקנת Zero וודאו קודם ש-zero --version עובד.
פירוק של כל טוקן
אפילו התוכנית הזעירה הזו כבר מדגימה את רוב מה שהופך את Zero לשונה. בואו נקרא אותה מההתחלה עד הסוף.
pub
pub מסמן הצהרה כציבורית: נראית מחוץ למודול הנוכחי שלה. סביבת הריצה צריכה למצוא את main מחוץ לתחום של הקובץ עצמו, ולכן main חייבת להיות pub. פונקציית עזר פרטית באותו קובץ לא הייתה צריכה את זה.
fun
fun פותח הצהרה על פונקציה. Zero משתמשת ב-fun, לא ב-fn (Rust), ב-func (Go) או ב-function (JavaScript). מילת מפתח אחת, שמשמשת באותה דרך בכל פעם.
main
שם נקודת הכניסה המקובל. כשיעד בר-הרצה של Zero רץ, סביבת הריצה מחפשת את pub fun main(world: World) וקוראת לה. אפשר לקרוא לפונקציות אחרות בכל שם שתרצו, אבל main שמור במוסכמה לנקודת הכניסה של התוכנית.
(world: World)
הפרמטר היחיד נקרא world והטיפוס שלו הוא World. סביבת הריצה בונה ערך World לפני הקריאה ל-main ומעבירה אותו פנימה. הערך הזה נושא את היכולות של התוכנית: גישה ל-stdout, ל-stdin, למערכת הקבצים, לרשת וכן הלאה, בהתאם למה שסביבת הריצה מחליטה להעניק.
את שם הפרמטר אתם בוחרים: גם (w: World) או (io: World) יתקמפלו בלי בעיה. המוסכמה בדוגמאות היא world, ונישאר איתה.
-> Void
טיפוס ההחזרה. Void אומר שהפונקציה לא מחזירה שום דבר שימושי: היא שם בשביל תופעות הלוואי שלה, לא בשביל הערך שלה. הרבה פונקציות שתכתבו יחזירו טיפוסים אמיתיים כמו i32 או shape שהגדרתם.
raises
raises לבדו (בלי טיפוס שגיאה ספציפי) על main אומר "הפונקציה הזו עלולה להיכשל". עבור main, המשמעות היא שהתוכנית יכולה לצאת עם סטטוס שאינו אפס אם check כלשהו בגוף מעביר שגיאה למעלה. צורות צרות יותר, למשל raises { InvalidInput }, נראה ב-Raises ו-Check.
check world.out.write("hello from zero\n")
זו השורה שבאמת עושה משהו. שלושה חלקים:
world.out: זרם הפלט הסטנדרטי, שחשוף כשדה על היכולתWorld..write("hello from zero\n"): מתודה שכותבת מחרוזת לזרם הזה. היא מחזירה תוצאה שיכולה לציין כישלון (הכתיבה עלולה להיכשל; הזרם עלול להיות סגור).check: מעביר את הכישלון הזה למעלה אם הוא קורה. בליcheck, הקומפיילר היה מתלונן שהתוצאה שלwriteנזרקת בשקט.
ה-\n בסוף הוא תו שורה חדשה. בלעדיו, הפלט לא היה עובר לשורה חדשה ושורת הפקודה של ה-shell הייתה מופיעה באותה שורה של ההודעה שלכם.
מה בדיוק קרה
כשהרצתם zero run hello.0:
- הקומפיילר ניתח את הקובץ שלכם ובדק את הטיפוסים שלו.
- הוא הפיק קובץ הרצה מקורי קטן עבור הפלטפורמה שלכם.
- סביבת הריצה בנתה יכולת
Worldעבור התהליך הנוכחי. - היא קראה ל-
main(world). - הקוד שלכם כתב "hello from zero\n" לזרם
outשל אותו world, שמחובר ל-stdout של הטרמינל שלכם. mainהחזירהVoid, סביבת הריצה ניקתה אחריה, והתוכנית יצאה עם סטטוס 0.
אין garbage collector, אין אתחול נסתר של סביבת ריצה, אין אתחול מרומז של מודולים. כל התוכנית היא הפונקציה שכתבתם, יחד עם קוד הספרייה הסטנדרטית שהיא קראה לו.
נסו שינוי קטן
גרמו לתוכנית ליצור קישור עבור ההודעה לפני שהיא כותבת אותה:
הריצו שוב: אותו פלט, אבל עכשיו ראיתם קישורי let ווידאתם שמחרוזות הן ערכים מלאים שאפשר להעביר ממקום למקום.
גרסה שנכשלת
מה קורה אם שוכחים את ה-check?
pub fun main(world: World) -> Void raises {
world.out.write("oops\n")
}
zero check hello.0 יסרב לקמפל את זה. התוצאה של write היא ערך שעלול להיכשל; התעלמות ממנו היא שגיאת קומפילציה. אתם צריכים לבצע עליו check (להעביר את השגיאה הלאה) או לטפל בו במפורש. זה אותו רעיון כמו תוצאות must_use ב-Rust, רק שכאן זה נאכף על כל קריאה שעלולה להיכשל.
הבא בתור: ה-CLI של Zero
השתמשתם כאן ב-zero run. ל-CLI יש קבוצה קטנה של פקודות שכדאי להכיר, check, run, build, test, fix, explain, ולכל אחת מהן יש מצב --json מובנה שנועד לצריכה על ידי סוכנים.
שאלות נפוצות
מהי תוכנית hello world ב-Zero?
ה-hello world הקנוני של Zero הוא חמש שורות: pub fun main(world: World) -> Void raises { check world.out.write("hello from zero\n") }. שמרו אותו בשם hello.0 והריצו zero run hello.0.
מה המשמעות של pub fun main ב-Zero?
pub fun main ב-Zero?pub הופך הצהרה לציבורית: נראית מחוץ למודול שלה. fun מצהיר על פונקציה. main היא נקודת הכניסה המקובלת ש-Zero מחפשת ביעד בר-הרצה. יחד, pub fun main מצהיר על נקודת הכניסה הציבורית שסביבת הריצה קוראת לה כשהתוכנית מתחילה.
למה main מקבלת פרמטר World?
World?ב-Zero אין קלט/פלט גלובלי. כל מה שמדבר עם העולם החיצון, stdout, stdin, קבצים, הרשת, עובר דרך יכולות שמועברות במפורש. סביבת הריצה מעבירה ל-main ערך World, והערך הזה (או חלקים ממנו) הוא הדרך היחידה שבה פונקציות יכולות לבצע קלט/פלט. כך תופעות לוואי נראות בחתימות של פונקציות.
מה עושים raises ו-check ב-hello world?
raises ו-check ב-hello world?raises על main מצהיר שהפונקציה עלולה להיכשל. check world.out.write(...) קורא לפונקציה שעלולה להיכשל, ואם היא נכשלת, מעביר את השגיאה למעלה אל הקורא: כאן זו סביבת הריצה, שיוצאת עם סטטוס שאינו אפס. בלי check, הקומפיילר יסרב לקמפל את הקריאה כי השגיאה לא תטופל.
באיזו סיומת קובץ Zero משתמשת?
קובצי מקור של Zero משתמשים בסיומת .0 (הספרה אפס, לא האות O). קובץ hello.0 הוא קובץ מקור של Zero. מפעילים את הקומפיילר עם פקודות כמו zero check hello.0 ו-zero run hello.0.