Erlang

Erlang (אֶרְלַנְג) היא שפת תכנות כללית ופונקציונלית אשר נוצרה על ידי מדעני המחשב ג'ו ארמסטרונג, רוברט וירדינג, ומייק ויליאמס ושוחררה לראשונה בשנת 1986.

Erlang תומכת הן בתכנות פונקציונלי והן בתכנות מקבילי ולפיכך נחשבת לשפה מרובת פרדיגמות תכנות. Erlang מתוכננת על מנת לתמוך בין היתר במערכות זמן אמת (מערכות אשר חייבות לעמוד במגבלת זמן מסוימת) מרושתות (Distributed). היא תומכת בין היתר בהצהרת קבועים, השמה וטיפוסיות דינמית. בנוסף, היא נחשבת ל-Fault Tolerant, כלומר, מסוגלת להמשיך לרוץ גם כאשר אחד מרכיביה נכשל, בהתאם לסגנון הקידוד "Let It Crash" ("תן לזה לקרוס"), המתבסס על ההנחה שקריסה של רכיב היא בלתי נמנעת, ולכן אין להשבית את כל המערכת בעקבות זאת.

ב-1986 כאשר היא יצאה לאור לראשונה, הייתה Erlang תוכנה פרטית (Proprietary Software) בראשות תאגיד התקשורת והטלקומוניקציה השוודי Ericsson. בשנת 1998 היא יצאה לאור כתוכנה חופשית ומגיעה עם ספריות העזר החופשיות OTP (קיצור של Open Telecom Platform).

== היסטוריה ==
השם Erlang, ששויך לשפה על ידי Bjarne Däcker, נובע משמו של המתמטיקאי הדני Agner Krarup Erlang, וכן מקיצור המילים "Ericsson Language" כלומר, השפה של תאגיד התוכנה אריקסון, אשר אחראי לפיתוח שפת התכנות.

הגרסה הראשונה של Elang מומשה בשפת התכנות פרולוג והושפעה משפות התכנות PLEX ו-Lisp.

== דוגמאות קוד ==
=== עצרת ===
מימוש פעולת העצרת ב-Erlang:<syntaxhighlight lang="erlang">
-module(fact). % This is the file 'fact.erl', the module and the filename must match
-export([fac/1]). % This exports the function 'fac' of arity 1 (1 parameter, no type, no name)

fac(0) -> 1; % If 0, then return 1, otherwise (note the semicolon ; meaning 'else')
fac(N) when N > 0, is_integer(N) -> N * fac(N-1).
% Recursively determine, then return the result
% (note the period . meaning 'endif' or 'function end')
%% This function will crash if anything other than a nonnegative integer is given.
%% It illustrates the "Let it crash" philosophy of Erlang.
</syntaxhighlight>

=== סדרת פיבונאצ'י ===
אלגוריתם רקורסיבי ב-Erlang אשר מייצר את סדרת פיבונאצ'י:<syntaxhighlight lang="erlang">
-module(series).
-export([fib/1]).

fib(0) -> 0;
fib(N) when N < 0 -> err_neg_val;
fib(N) when N < 3 -> 1;
fib(N) -> fib_int(N, 0, 1).

fib_int(1, _, B) -> B;
fib_int(N, A, B) -> fib_int(N-1, B, A+B).
</syntaxhighlight>

=== Quicksort ===
אלגוריתם המיון Quicksort ב-Erlang:<syntaxhighlight lang="erlang">
%% Sort a list of items
-module(qsort). % This is the file 'qsort.erl'
-export([qsort/1]). % A function 'qsort' with 1 parameter is exported (no type, no name)

qsort([]) -> []; % If the list [] is empty, return an empty list (nothing to sort)
qsort([Pivot|Rest]) ->
 % Compose recursively a list with 'Front' for all elements that should be before 'Pivot'
 % then 'Pivot' then 'Back' for all elements that should be after 'Pivot'
 qsort([Front || Front <- Rest, Front < Pivot]) ++
 [Pivot] ++
 qsort([Back || Back <- Rest, Back >= Pivot]).
</syntaxhighlight>

== סוגי נתונים בשפה ==

ב-Erlang ישנם 8 סוגי נתונים פרימטיביים:
* Integers (מספרים שלמים) –
* Atoms – נכתבים כמחרוזות של תווים אלפאנומרים עוקבים, כאשר הראשון הוא אות קטנה (lowercase). משמשים על מנת לציין ערכים שונים.
* Floats – משתנים עשרוניים (Floating Point Numbers).
* References – התכונה היחידה של סמלים אלו היא שניתן להשוות ביניהם. הם נוצרים על ידי הפעולה <code>(...)make_ref</code>.
* Binaries – אוסף של בתים (bytes). בית בהגדרתו הוא 8 סיביות, כלומר, 8 ספרות בינאריות.
* Pids – קיצור ל-Process Identifiers (מזהי תהליכים). Pid הוא הפניה לתהליך של Erlang והוא נוצר על ידי הפעולה <code>(...)spawn</code>.
* Ports – פורטים נוצרים על מנת לתקשר עם העולם החיצוני. הם נוצרים עם הפעולה המובנית <code>open_port</code>. הודעות יכולות להישלח ולהתקבל מפורטים, אך הן חייבות למלא אחר פרוטוקול אשר נקרא "port protocol".
* Funs (קיצור של Functions) – פונקציות, פעולות. הן נוצרות בתחביר הבא: <code>fun(...) -> ... end</code>.

ושלושה סוגי נתונים מורכבים:
* Tuples – מבני נתונים אשר מכילים מספר קבוע של נתונים. להמחשה, קטע הקוד <code>{D1,D2,...,Dn}</code> מציין tuple שאבריו <code>D1, D2, ... Dn</code>.
* Lists – רשימות.
* Maps (מילון, Dictionary) – רשימה של זוגות של key (מפתח) ו-(value). בדומה למילון פשוט, אשר מכיל רשימה שמכילה זוגות של מילה והתרגום שלה. נכתב בתחביר הבא: <code>#{Key1=>Value1,...,KeyN=>ValueN}</code>.

ושתי צורות של סוכר תחבירי:
* Strings – רשימה של תווים המוגדרת בדרך כלל באמצעות גרשיים כפולים (מירכאות), כקיצור לרשימה עם ערכי ה-unicode של התווים. לדוגמה, ניתן לייצג את המילה cat (שמשמעותה בעברית חתול) כך: <code>״cat״</code> וכך: <code>[99,97,116]</code>.
* Records – מאפשרים דרך נוחה לשייך תג לכל איבר ב-tuple, כלומר, לפנות לאלמנט ב-tuple באמצעות שם ולא מקום (מציין, אינדקס). תהליך אשר מתקיים לפני ההידור לוקח את הגדרת ה-Record ומחליף במקומו את המקום המתאים כאשר מתייחסים אליו.

ב-Erlang אין פעולה על מנת להגדיר מחלקות, אך ישנן ספריות חיצוניות זמינות לכך.<ref></ref>

== טיפול בקריסות ==
=== Defensive Programming ("תכנות הגנתי") ===
ברוב שפות התכנות האחרות, קריסות תוכנה נחשבות ללא רצויות ולכן יש להימנע מהן בכל מחיר. לכן, נהוג ללכוד את התקלות, ולאחר מכן להתמודד עם השפעתן – תהליך אשר נקרא Exception Handling. פילוסופית התכנון הזו נובעת בין היתר מכך שעקרונות פיתוח תוכנה רבים נקבעו בתקופה שבה מחשבים היו בעלי מעבד יחיד. בתנאים אלו, קריסות תוכנה אכן היו הרסניות. כתוצאה מכך, הפך סגנון תכנות בו חלק נרחב מהקוד מושקע לטיפול בקריסות תוכנה לנפוץ ביותר. סגנון זה, בו משקיעים משאבים אלו לטיפול בקריסות, נקרא "Defensive Programming" ("תכנות הגנתי").

=== Let It Crash ("תן לזה לקרוס") ===
מתכנני Erlang הבינו כי אף על פי השלכותיהן השליליות, קריסות תוכנה הן בלתי נמנעות. לכן, במקום לטפל בקריסה נקודתית כמצב חירום אשר משהה את כל הפעילות הרגילה עד למציאת פתרון, הם חשבו שיהיה יותר רציונלי לטפל בקריסה נקודתית בדיוק כמו אירוע (event) אחר בזמן ריצה. לכן, כאשר תהליך ב-Erlang קורס, סיטואציה זו מדווחת רק כסוג אחר של הודעה.

==== ההשלכות על עיצוב Erlang ====
סגנון זה השפיע על הפיצ'רים הבסיסיים של השפה:
* ב-Erlang אין זיכרון גלובלי משותף – לכל תהליך יש זיכרון מבודד משלו
* תהליכים ב-Erlang יכולים:
** להיווצר בקלות
** לתקשר רק באמצעות העברת מסרים
** לפקח אחד על השני. הדבר מאפשר היררכיות בין תהליכים (Supervisor Trees).
* על תהליך לבצע את משימתו או להיכשל
* כישלון תהליך מדווח כהודעה.

=== Supervisor Trees (עצי פיקוח) ===
ביישום טיפוסי ב-Erlang תהליכים מנוהלים בצורה של עץ פיקוח. ארכיטקטורה זו מבוססת על ההיררכיה של תהליכים, כאשר התהליך בעל המעמד הגבוה נקרא supervisor והוא אחראי על פיקוח וניהול של תהליכים שבחסותו (Child Proccesses). גם תהליך אשר נמצא בפיקוח על ידי תהליך אחר בעל מעמד גבוה יותר בהיררכיה, יכול לפקח על תהליכים משלו, וכך נוצרת היררכיה בעלת תהליכים רבים אשר מפקחים ומפוקחים. על העץ המפקח בין היתר נדרש לטפל במקרי קצה של התהליכים שבחסותו – כגון קריסה שלהם. במקרה של קריסה של אחד מהם יקבל העץ המפקח הודעה המכילה tuple שאיברו הראשון יהיה הערך מסוג הנתונים Atom (אטום) <code>'DOWN'</code>.

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

== מימוש ==
המימוש הרשמי של Erlang משתמש ב-BEAM – המכונה הווירטואלית של Erlang.

BEAM כלולה בהפצה הרשמית של Erlang, שנקראת Erlang/OTP. היא מריצה Bytecode אשר מומר בזמן ריצה ל-Threaded code . בנוסף המימוש הרשמי מכיל מהדר אשר נוצר על ידי HiPE (ראשי תיבות של Performance Erlang Project) באוניברסיטת אופסלה בשוודיה, וגם מפרש אשר ממיר ישירות מקוד מקור באמצעות עץ נתונים – abstract syntax tree. מאז אוקטובר 2001, המהדר נמצא באינטגרציה מלאה עם המימוש Erlang/OTP.

== ראו גם ==
* טלקומוניקציה
* Lisp
* תכנות פונקציונלי

== קישורים חיצוניים ==

*
*[https://erlang.org/doc/apps/stdlib/stdlib.pdf הדוקומנטציה הרשמית של השפה (מדריך בעל 555 עמודים)]

==הערות שוליים==

קטגוריה:טלקומוניקציה
קטגוריה:שפות תכנות פונקציונליות
קטגוריה:שפות תכנות