ללמוד erlang

יש לי רשימה מאוד ארוכה של שפות תכנות שאני רוצה ללמוד אותם. הידע שלי של קרוב ל24 שפות תכנות לא מספיק, והרעב עדיין גדול מאוד, אז אחרי הרבה התלבטויות מה השפה ללמוד, החלטתי ללכת בראש ובראשונה על erlang, וכרגע אני עושה את הצעדים הראשונים שלי בשפה. השם של השפה, כמו שפה אחרת שאני מאוד אוהב לתכנת בה, גם היא על שם מתמטיקאי (בשם Agner Krarup Erlang), והיא מבית Ericsson, וחלק אומרים שהשם של השפה בכלל לקוח ממשחק המילים Ericsson Language.

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

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

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

  X = 10 .

אז אני לא יכול להגיד אח"כ ש X שווה ל20. כלומר "נתון" כי X הוא בעצם "10". אפשר לחשוב על זה כעל קבוע בשפות כמו פסקל. הנקודה בסוף השורה אומרת שהשורה/ביטוי הסתיים (כמו נקודה פסיק בשפות אחרות).

יש עוד משהו בשפה שנקרא atom. זהו למעשה שם המתחיל או באות קטנה או באות גדולה (למעשה משתנה הוא גם atom), אבל הוא יותר דומה לרעיון של symbol ברובי, מאשר משהו אחר. האות הגדולה בהכרח תגיד שהוא משתנה.

השפה מחזיקה מספר קטן של טיפוסי נתונים:

  • מספר שלם (Integer)
  • מספר עשרוני (Float)
  • נקודת ייחס (Reference) – עדיין אני לא מבין את זה לעומק, אבל זה נועד להשוות ערכים ממש בגדול
  • pid – ממש כמו ביוניקס/לינוקס, מספר המזהה תהליכון, כלמור process id.
  • port – מדבר עם דברים שהם לא שייכים אלייך, לא ברור לי יותר מזה כרגע
  • Binary – מחזיק ערכים מספריים בקבוצה בסדר מסויים.
  • Funs – פונקציות אנונימיות

השפה גם מחזיקה רשימות (או מערכים בשפות אחרות) ובנוסף גם tuple שמעולם לא הבנתי איך לתרגם את זה לעברית (לא שזה דבר רע). פיתון קרובה יותר להגדרה של מה ששני המבנים עושים. אך ב tuple זה לא בהכרח key-value, אם כי כמו בהרבה שפות (כולל פרל ורובי), אפשר להגיד שהערך הראשון זה השם והשני הוא התוכן.
רשימה מוצגת בצורה הבאה:

  [X, 1, 'Hello', true].

כאשר tuple נראה בצורה הבאה:

   {X, 1, 'Hello', true}.

חשוב להבין כי אין טיפוס בוליאני בשפה, ו true ו false הם סוג של atom שנמצא בשימוש.
מחרוזת בerlang היא בעצם סוכר סינטטי לרשימת בתים. כלומר "a" בעצם נשמר כ 65 -> מספר ה ascii שלו. על מנת לעבוד עם a כמחרוזת, אפשר לכתוב את הקוד הבא:

  $a .

כלומר זה אומר לשפה שמדובר בתו ולא ב atom.
כמו כן, יש גם "רשומות" בשפה, אבל גם הם בעצם סוג של סוכר סינטטי, אשר משתמש בעצם ב tuple אשר ערך אחד משמש כשם, והשני כתוכן שלו (ראו ערך השם-ערך שהזכרתי למעלה).
פעולת השוויון שהצגתי עם X, ובכן חשוב להבין כי זו לא פעולת הצבה, אלא ממש שוויון, כלמור השוותי את X ל10. כך בעצם השפה עובדת. כך שבעצם יש פעולה של שוויון, האם משהו שווה למשהו אחר. ז"א שהשורה הראשונה תצליח, אבל לא השנייה:

  {1, 'hello'} = {1, 'hello'}.
  {a, true}    = {b, false}.

השפה מנסה להשוות את צד שמאל לצד ימין, ואז מנסה לאזן בין שניהם. בשורה השנייה, לא ניתן לבצע איזון בין 2 הצדדים, היות ו a זה לא b (כל אחד מהם הוא atom שונה), ואותו הדבר גם עם true ו false.

דרך לעשות את הדברים בצורה קרובה יותר להצבה היא באמצעות השימוש בצד שמאל משתנה, ובצד ימין הערכים/atom שרוצים:

{A, {B, C}} = {first, {second, third}}.

מה שקורה הוא ש A יכיל את first, וכמו שאתם מבינים, B יכיל את second ולכן C יכיל את thrid.
ועכשיו המשפט "שקול" ולכן שווה (חשיבה מתמטית, זוכרים ?).
אי אפשר אבל עכשיו לשנות את הערכים של המשתנים, והם לא יוצבו מחדש. כך ובמידה ונרצה כי יהיו משתנים אחרים עם אותו הערך, נהיה צריך להגדיר גם אותם, כלומר:

{X, Y} = {first, {second, third}}.

שימו לב כי Y מכיל למעשה את הערך {second, third} . ההצבה הזו בעצם עושה bound (בשפת erlang) – כלומר קישור למשתנה עצמו.
מידע "נקי" ללא משתנה נחשב ל unbound.
כאשר אנחו מציבים ערך שהוא bounded, אז אפשר להשוות אותו לערך שהוא unbounded אבל במידה והם לא זהים, תהיה לנו חריגה על הנושא.

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

-module(factorial).
-export([factorial/1]).

factorial(0) -> 1.
factorial(N) ->
    N * factorial(N-1).

חלק ה module הוא הדרך להגיד לשפה שאנחנו יוצרים קוד שיהיה זמין גם חיצונית, כלומר מודול.
חלק ה export מספק מידע על חלק ה arity של הפונקציה, כלומר כמות פרמטרים שיעברו במקרה הזה.
אח"כ אנחנו אומרים לerlang כי במקרה שהפרמטר הוא 0, אנחנו מחזירים 1. ערך אחר, הוא יבצע את הפעולה של N כפול הערך של N פחות אחד, וכל זה יתממש כל עוד לא הגענו בעצם לערך של 0.

חלק שאני לא מבין כרגע לעומק (אבל רק התחלתי ללמוד, אז תסלחו לי :)), הוא הנושא של tail recursive. עד כמה שאני מבין, הפונקציה factorial היא פונקציה שהדבר האחרון שרץ בה הוא פעולת הכפל, ולא הרקורסיה, מה שאומר כי לא תמיד נקבל את מה שבאמת רצינו. לפי דוגמה שמצאתי, זה אמור להיות משהו כזה:

-module(factorial).
-export([factorial/1]).

factorial(N) ->
    factorial(N,1).<br><br>factorial(0, Acc) ->
    Acc,
factorial(N,Acc) ->
    factorial(N-1, N*Acc).

אך אני לא מבין את זה כרגע לעומק להסביר.

זהו בנתיים. לא רע להספק של שעתיים של קריאה בנושא 🙂

3 מחשבות על “ללמוד erlang

  1. רפי

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

  2. פינגבק: הרעיון של תכנון מערכות גמישות – חלק ראשון | לראות שונה

כתיבת תגובה

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

הלוגו של WordPress.com

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

תמונת Twitter

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

תמונת Facebook

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

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

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

מתחבר ל-%s