להבין את רובי

לאחרונה יצא לי לגעת בקוד הראשון ביותר שאי פעם כתבתי בשפת רובי, ואני חייב לציין שאינני יודע באיזו שפה זה כתוב, התחביר אומנם רובי, אבל הקוד נראה הכלאה בין ג'אווה לבין פרל – לא רובי. חשוב לציין שב2006 כאשר כתבתי אותו, כתבתי אז בעיקר ב2 השפות האלו, ובכלל לא ברובי…

רובי היא שפה שהיא Object Oriented אמיתית, בה פיזית הכל הוא אובייקט. אין primitives כמו בג'אווה אלא ממש הכל הוא אובייקט. אם זה מספר, או תו או כל דבר אחר.

עד רובי 1.8.7 כולל, האובייקט הנמוך ביותר ברובי נקרא Object. ברובי 1.9 (גרסת הפיתוח של גרסה 2), יש אובייקט שObject יורש ממנו הנקרא BasicObject. התוספת נבנתה מצד אחד ליצור תאימות לאחור, תוך כדי יצירה של אובייקט אב המכיל כמעט לגמרי כלום.

ברובי אין בכלל אופרטורים. כל דבר הנראה כאופרטור הוא בעצם מתודה. כך שאין צורך לכתוב operator overload כמו בשפת פסקל למשל, אלא מתודה שיודעת לבצע את הפעולה מול המשתנה (או המשתנים) בצד השני.

כמו כן, סוגריים ברובי הם לא דבר שחייבים להשתמש בו, אבל יש מקומות בהם צריך להשתמש בהם, בשביל הבהרה מה שייך למה, ויש מקומות בהם אין תועלת מכך ברמת ההבנה שלנו כמתכנתים. כל עוד המפרש של רובי מבין מה רצינו ומספק את התוצאה, לו זה לא משנה.

נהוג ברובי שכל מידע שנמצא במיכל כלשהו (כאשר אפילו מחרוזת היא מיכל של תווים), אז ניתן לגשת למידע בצורה של גישה לכל מיקום של איבר או כאשר צריך לרוץ על הכל, להשתמש באיטרטורים במקום. כלומר לא לבצע לולאת for מה0 ועד לאורך המקסימום. או לגשת למיקום ספציפי או לרוץ על הכל עם איטרטורים שיש לאותו אובקייט להציע.

עכשיו נשאלת השאלה, מה קורה כאשר רוצים למחוק איבר מסויים, או ערך שמכיל חוק מסויים ? ובכן, אם מדובר באיבר שאנחנו יודעים היכן הוא נמצא, אפשר למחוק על ידי המתודה המתאימה את האיבר הזה (כדוגמת delete למיקום, או לערך), אבל אם אנחנו רוצים למחוק איברים לפי חוק מסויים, ובכן הדרך הלא נכונה, זה להריץ איטרטור פשוט ולמחור את הערך. הדרך הנכונה היא להשתמש במתודות כדוגמת delete_if אשר מקבלת Proc שמכיל תשובה חיובית אם התוכן שעבר למשתנה מסויים מכיל את החוקיות שאנחנו רוצים.

למה אי אפשר להשתמש באיטרטור אלא במתודות כדוגמת delete_if ? בגלל שהאיטרטור לא רק מכיל את הערך, אלא גם את הכתובת של המידע. במידה ונשכתב את הכתובת של המשתנה לאיטרטור בגלל המידע שהוא מכיל, אנחנו גורמים לתופעות מוזרות, כדוגמת איבוד כתובות של המשתנה הבא, או שינוי הכתובת הבאה במקום וכו'. היות וזה המצב, לא ניתן או מומלץ לגעת במשתנה של איטרטור על מנת לבטל את האיבר, או להוסיף לידו עוד איבר.

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

==
===
eql?
equal?
  • המתודה הראשונה (==) משווה בין ערכים, כלומר האם הערך בצד השמאלי שווה לערך בצד הימני. כלומר אם צד אחד הוא 10 והצד השני הוא 10.0 (עשר נקודה 0) התשובה תהיה חיובית.
  • המתודה השנייה (===) מקבילה להשווה של case לרוב (אם אי היא מגיעה מרמת Object, ולכן יכולים לשכתב אותה) עבור כל איבר מצד שמאל עבור צד ימין. כלומר אם צד אחד הוא 10, והצד השני הוא 10.0 (עשר נקודה 0), התשובה תהיה חיובית, אבל לא אותו הדבר עבור 10.1 (עשר נקודה אחד).
  • המתודה השלישית (‎eql?) ‏ משווה האם הערך בצד שמאל זהה לצד הימני, וגם אותו סוג אובייקט. כלומר אם אני משווה בין 10 לבין 10.0 (עשר נקודה 0), אז אני אקבל תשובה שלילית, היות ואחד הוא Fixnum והשני הוא Float.
  • המתודה הרביעית (equal?) משווה בין אובייקטים. האם האובייקט הראשון שווה לאובייקט השני. או במילים האחרות האם מדובר באותו אובייקט. כלומר אם אני משווה בין 10 לבין 10.0 (עשר נקודה 0), אז אני אקבל תשובה שלילית, היות ואחד הוא Fixnum והשני הוא Float.

עוד נושא מעניין הוא ערך בר שינוי לבין ערך שאינו בר שינוי. בשפות כדוגמת פסקל, אפשר לעבוד עם 2 סוגים של "קבועים". כלומר סימן שתמיד מתחלף לערך, וסימן שתמיד מכיל בתוכו ערך, אבל אפשר לשנות אותו בזמן ריצה (ואף בקובץ הריצה עצמו, אבל לא אכנס לנושא הזה מן הסתם), אבל הוא אינו משתנה "רגיל", אלא מוגדר כקבוע. ברובי לעומת זאת, יש קבוע ויש משתנה. אבל משתנה בר שינוי (mutable) ומשתנה שאינו בר שינוי (immutable) יכול להתקיים למשתנה רגיל ולקבוע. חשוב אבל להבין שהערך (כלומר האובייקט שהוא מצביע אליו) של המשתנה יכול להשתנות. אבל התוכן (של האובייקט) שהוא מכיל אינו יכול להשתנות. מה הכוונה ?

אני יכול להציב ערך חדש לגמרי, כלומר אובייקט חדש לגמרי למשתנה וגם לקבוע (בקבוע נקבל הודעת אזהרה על כך אבל). אבל אני לא יכול למשל למחוק איבר ממערך שהוא אינו בר שינוי, או להוסיף לו איבר. אנחנו ניצור ערך לא בר שינוי על ידי שימוש במתודה freeze. ונוכל לבדוק האם הערך אינו בר שינוי על ידי המתודה של frozen? (סימן השאלה בסוף). חשוב להבהיר כי לא ניתן להפשיר אובייקט שהוקפא.

מחשבה אחת על “להבין את רובי

  1. פינגבק: להבין את רובי 2 | לראות שונה

כתיבת תגובה

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

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s