ارلنگ

ارلنگ  یک زبان برنامه‌نویسی همه‌منظوره، همروند، دارای زباله جمع‌کن و سامانهٔ زمان‌اجرا  است. برای همروندی از مدل اکتور  پیروی می‌کند. این زبان توسط شرکت اریکسون برای پشتیبانی و توسعه برنامه‌های توزیع‌شده، تحمل‌پذیر در برابر خطا، بیدرنگ نرم  و بدون وقفه طراحی شده‌است. اریکسون برای طراحی نرم افزار های سوییچینگ تلفن قبلا از زبانی به نام PLEX استفاده میکرده که این زبان بسیار شبیه Erlang بوده منتهی مشکلاتی داشته که Erlang بطور کامل آنها را رفع کرده. این زبان از تعویض داغ  که در آن بدون توقف سامانه، قادر به تغییر کدهای برنامه هستیم پشتیبانی می‌کند.

سیستم زمان اجرا ارلنگ برای طراحی سیستم هایی که نیازمند خصوصیات زیر هستند استفاده میشود (به نوع ماشین مجازی ارلنگ این امکانات را دارد):
 توزیع شده 
 بردباری خطا 
 زمان واقعی ملایم 
 بسیار در دسترس، بدون توقف 
 تعویض داغ  که در آن کد می‌تواند بدون توقف سیستم تغییر کند.

زبان برنامه‌نویسی ارلنگ برای خواص زیر شناخته می‌شود:
 داده تغییرناپذیر 
 تطبیق الگو 
 برنامه‌نویسی تابعی 

ارلنگ در واقع یک زبان اختصاصی در شرکت اریسکون بود که توسط جو آرمسترانگ، رابرت ویردینگ و مایک ویلیامز در سال ۱۹۸۶ توسعه پیدا کرده بود، اما در سال ۱۹۹۸ به عنوان یک زبان متن باز منتشر شد. Erlang/OTP توسط واحد محصول OTP در اریکسون پشتیبانی و نگهداری می‌شود.Hitchhiker’s Tour of the BEAM – Robert Virding http://www.erlang-factory.com/upload/presentations/708/HitchhikersTouroftheBEAM.pdf

 تاریخچه 
نام «ارلنگ» توسط Bjarne Däcker که سرپرست آزمایشگاه و تیم طراحی ارلنگ بوده انتخاب شده. این نام از دو جهت قابل ملاحظه و جالب هست ابتدا اینکه از نام یک مهندس و ریاضی دان دانمارکی Agner Krarup Erlang گرفته شده که این فرد در زمینه مخابرات هم فرمولی دارد (Erlang formula) و از طرفی هم از مخفف Ericsson Programming Language گرفته شده.ارلنگ با هدف بهبود و توسعه برنامه‌های کاربردی تلفن طراحی شده‌است. نسخه اولیه ارلنگ در پرولگ  اجرا شد و توسط زبان برنامه‌نویسی مورد استفاده در PLEX مبادلات زودتر اریکسون تأثیر پذیرفته بود. در سال ۱۹۸۸ ارلنگ ثابت کرده بود که برای نمونه‌سازی مبادلات تلفنی مناسب است، اما در prolog بسیار آهسته اجرا می‌شد. یک گروه از متخصصان اریکسون تخمین زده بودند که برای استفاده از محصولشان سرعت آن باید ۴۰ بار سریعتر شود بنابراین در سال 1992 شروع به بازنویسی آن با زبان C کردند و ماشین مجازی BEAM متولد شد. نحوه عملکرد ماشین مجازی BEAM ترکیبی از کدهای NATIVE و تفسیر مستقیم برای ایجاد تعادل بین حجم کدها و افزایش عملکرد محیط اجرا است. با توجه به گفته‌های آرمسترانگ، این زبان زمانی از یک محصول آزمایشگاهی به یک محصول واقعی تبدیل شد که در طراحی نسل جدید AXE به AXE-N در سال ۱۹۹۵ استفاده شد با این موفقیت در نتیجه Erlang برای سویچ های شبکه از نوع ATM (Asynchronous Transfer Mode) هم انتحاب شد.

بندانگشتی|جایگزین=سوییچ مخابراتی اریکسون|سوییچ مخابراتی اریکسون
بندانگشتی|Robert Virding
بندانگشتی|جایگزین=Bjarne Däcker|Bjarne Däcker

در سال ۱۹۹۸ اریکسون از سوئیچ AXD301 اطلاع داد، که شامل بیش از یک میلیون خط از ارلنگ می‌شد و از در دسترس بودن بالای ۹ گزارش داد. مدت کوتاهی پس از آن، سیستم رادیو ارلنگ استفاده از ارلنگ برای محصول جدید در مصارف خانگی را ممنوع کرد، این اتفاق با استناد به اولویت 
زبان‌های غیررسمی روی داد. این ممنوعیت باعث شد آرمسترانگ و دیگران شرکت اریکسون را ترک کنند. اجرای متن بازکردن این زبان در انتهای همین سال روی داد. سرانجام با برداشتن این ممنوعیت اریکسون دوباره آرمسترانگ را در سال ۲۰۰۴ استخدام کرد.

در سال ۲۰۰۶، پشتیبانی از چند پردازنده‌ای متقارن محلی به سیستم زمان اجرا و ماشین مجازی اضافه شد.

 جهان بینی ارلنگ 
دیدگاه ارلنگ از جهان، از زبان جو آرمسترانگ، یکی از سازنده گان ارلنگ که خلاصه‌ای از آن را در پایان‌نامه دکترای خود به شرح زیر آورده:
 همه چیز یک فرایند است.
 فرایندها به شدت منزوی هستند.
 ایجاد و تخریب فرایند یک عملیات سبک‌وزن است.
 عبور پیام تنها راه تعامل فرایند هاست.
 فرایندها نام‌های منحصر به فردی دارند.
 اگر شما نام یک فرایند را بدانید می‌توانید به آن پیام ارسال کنید.
 فرایندها بدون منبع به اشتراک گذاشته می‌شوند.
 دست زدن به خطا  غیر محلی است.
 فرایندها کارهایی که پشتیبانی می‌کنند را انجام می‌دهند که منجر به انجام یا شکست می‌شود.

جو آرمسترانگ در سال ۲۰۱۳ در مصاحبه با Rackspace اشاره می‌کند: «اگر جاوا یک بار نوشته شود و همه جا اجرا شود، پس ارلنگ یک بار نوشته می‌شود و همیشه اجرا می‌شود.»
 استفاده 
ارلنگ در حال حاضر توسط شرکت‌ها از جمله سیسکو سیستمز, متا پلتفرمز, نورتل و تی-موبایل استفاده شده‌است. ارلنگ در گره پشتیبانی اریکسون، و 3G , GPRS و شبکه‌های LTE در سرار جهان مورد استفاده قرار می‌گیرد. در حقیقت بیشتر ترافیک اینترنت بصورت مستقیم یا غیر مستقیم از طریق ارلنگ مدیریت میشود, هر زمان که از تلفن ثابت یا تلفن همراه و یا اینترنت استفاده میکنیم در حقیقت در حال استفاده از ارلنگ هستیم.Wikipedia contributors, "Erlang (programming language)," Wikipedia, The Free Encyclopedia, http://en.wikipedia.org/w/index.php?title=Erlang_(programming_language)&oldid=417616995 (accessed March 10, 2011).Wikipedia contributors, "Erlang (programming language)," Wikipedia, The Free Encyclopedia, https://en.wikipedia.org/wiki/Erlang_(programming_language)

 مفاهیم کلیدی 
در Erlang، فرایندها (processes)، پایش‌ها (monitors) و ناظران (supervisors) مفاهیم مهمی برای ساخت برنامه‌های مقاوم در برابر خطا و قابل مقیاس هستند:

فرایندها

- فرایندهای Erlang واحدهای اجرای سبک، جداگانه و همزمان هستند.

- آنها با استفاده از توابع `()spawn` ایجاد می‌شوند و از طریق پیام‌های غیرهمزمان با هم ارتباط برقرار می‌کنند.

- فرایندها می‌توانند با استفاده از توابع `register/2` و `whereis/1` تحت نام‌های ثبت شده برای آدرس‌دهی آسان‌تر ثبت شوند.

پایش‌ها

- پایش‌ها پیوندهای یک‌طرفه بین فرایندها هستند که به یک فرایند امکان می‌دهند فرایند دیگری را پایش کند.

- یک پایش با استفاده از `erlang:monitor/2` ایجاد می‌شود و فرایند پایش‌کننده پیام `'DOWN'` دریافت می‌کند اگر فرایند پایش‌شده پایان یابد.

- پایش‌ها برای فرایندهای خارجی که به وضعیت فرایند دیگری علاقه‌مند هستند اما مسئول مستقیم آن نیستند مفید هستند.

ناظران

- ناظران فرایندهای ویژه‌ای هستند که مجموعه‌ای از فرایندهای فرزند را پایش و کنترل می‌کنند، که می‌توانند کارگران (workers) یا ناظران دیگر باشند.

- ناظران یک استراتژی راه‌اندازی مجدد برای مدیریت شکست‌های فرایندهای فرزند تعریف می‌کنند، مانند one_for_one (فقط فرزند شکست‌خورده را راه‌اندازی مجدد کن)، one_for_all (همه فرزندان را راه‌اندازی مجدد کن) یا rest_for_one (فرزند شکست‌خورده و آنهایی را که پس از آن هستند را راه‌اندازی مجدد کن).

- ناظران با استفاده از یک ماژول بازخورد که توابعی مانند `init/1` را صادر می‌کند تعریف می‌شوند تا فرایندهای فرزند و استراتژی راه‌اندازی مجدد را مشخص کنند.

- درختان نظارتی (supervision trees) چیدمان سلسله‌مراتبی ناظران و کارگران هستند که یک روش ساختاریافته برای ساخت برنامه‌های مقاوم در برابر خطا فراهم می‌کنند.

به طور خلاصه، فرایندها واحدهای اجرای پایه را فراهم می‌کنند، پایش‌ها به فرایندها امکان می‌دهند یکدیگر را زیر نظر بگیرند، و ناظران سلسله‌مراتبی از فرایندها را با سیاست‌های راه‌اندازی مجدد تعریف‌شده هماهنگ می‌کنند. به طور یکپارچه، آنها ساخت برنامه‌های مقاوم Erlang خودترمیم را امکان‌پذیر می‌سازند.

 نمونه برنامه‌نویسی تابعی 
یک تابع ارلنگ که از توابع بازگشتی برای شمارش تا ده استفاده می‌کند:

-module(count_to_ten).
-export([count_to_ten/0]).

count_to_ten() -> do_count(0).

do_count(10) -> 10;
do_count(N) -> do_count(N + 1).

الگوریتم اجرای فاکتوریل در ارلنگ:

-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.

الگوریتم اجرای فیبوناچی در ارلنگ (توجه داشته باشید: این الگوریتم فقط برای نشان دادن نحوه نگارش ارلنگ است و از نظر زمانی بهینه نیست):

-module(fibonacci). % This is the file 'fibonacci.erl', the module and the filename must match
-export([fib/1]). % This exports the function 'fib' of arity 1

fib(0) -> 0; % If 0, then return 0, otherwise (note the semicolon ; meaning 'else')
fib(1) -> 1; % If 1, then return 1, otherwise
fib(N) when N> 1 -> fib(N - 1) + fib(N - 2).

مرتب‌سازی سریع در ارلنگ، با استفاده از لیست درک مطلب:

%% qsort:qsort(List)
%% 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]).

در مثال بالا تابع فراخوانی بازگشتی مرتب‌سازی سریع تا زمانی که چیزی برای مرتب‌سازی باقی نمانده باشد ادامه پیدا می‌کند .
عبارت [Front || Front <- Rest, Front <Pivot] یک لیست درک است، به این معنی «ساخت یک لیست از عناصر Front به‌طوری‌که Front عضو Rest است، و Front کمتر از Pivot است.» ++ عملگر الحاق لیست است.
یک تابع مقایسه می‌توان برای سازه‌های پیچیده‌تر به خاطر خوانایی استفاده می‌شود.
کد زیر لیست‌ها را بر اساس طول مرتب می‌کند:

% This is file 'listsort.erl' (the compiler is made this way)
-module(listsort).
% Export 'by_length' with 1 parameter (don't care about the type and name)
-export([by_length/1]).

by_length(Lists) -> % Use 'qsort/2' and provides an anonymous function as a parameter
   qsort(Lists, fun(A,B) -> length(A) <length(B) end).

qsort([], _)-> []; % If list is empty, return an empty list (ignore the second parameter)
qsort([Pivot|Rest], Smaller) ->
    % Partition list with 'Smaller' elements in front of 'Pivot' and not-'Smaller' elements
    % after 'Pivot' and sort the sublists.
    qsort([X || X <- Rest, Smaller(X,Pivot)], Smaller)
    ++ [Pivot] ++
    qsort([Y || Y <- Rest, not(Smaller(Y, Pivot))], Smaller).
در اینجا، دوباره یک Pivot از اولین پارامتر داده شده به ()qsort گرفته شده‌است و نام لیست rest را Rest قرار داده‌است. توجه داشته باشید که بیان
[X || X <- Rest, Smaller(X,Pivot)]
تفاوتی با حالت زیر ندارد
[Front || Front <- Rest, Front <Pivot]
(در مثال قبل) به جز برای استفاده از یک تابع مقایسه‌ای در آخرین بخش، صدا زدن"ساخت یک لیست از عناصر X به‌طوری‌که X یک عضو از Rest است، و Smaller درست می‌باشد." با Smaller از پیش تعریف شده مانند
fun(A,B) -> length(A) <length(B) end
توجه داشته باشید تابع بی‌نامی که Smaller ، در لیست پارامتر تعریف دوم qsort هست را می‌توان با نامی که در تابع اشاره شده نامید.

 انواع داده 
 Integers 
اعداد صحیح به عنوان دنباله‌ای از اعداد اعشاری نوشته شده‌است، به عنوان مثال، ۱۲، ۱۲۳۷۵ و -۲۳٬۴۲۷ اعداد صحیح هستند. علم حساب اعداد صحیح دقیق و تنها محدود به حافظه موجود بر روی دستگاه است.

 Atoms 
اتم‌ها در یک برنامه برای نشان دادن ارزش‌های متمایز استفاده می‌شود. آن‌ها به صورت رشته‌ای از کاراکترهای الفبایی متوالی نوشته می‌شوند، اولین کاراکتر که حروف کوچک است. اتم‌ها می‌توانند شامل هر کاراکتر باشند اگر آن‌ها در نقل قول‌های محصور و یک کنوانسیون فرار وجود داشته باشد که اجازه می‌دهد هر کاراکتر در یک اتم استفاده شود.

 Floats 
عداد ممیز شناور از IEEE 754 بیتی۶۴ استفاده می‌کند.

 Reference 
مراجع نمادهای منحصر به فرد جهانی هستند که تنها ویژگی آن‌ها این است که می‌توان آن‌ها را برای برابری مقایسه کرد.

نوع داده مرجع در زبان ارلنگ :
در ارلنگ، یک مرجع یک عبارت منحصر به فرد است که برای شناسایی یک فرآیند یا منبع خاص در سیستم زمان اجرای ارلنگ ایجاد می‌شود. این منحصر به فرد بودن باعث می‌شود که مراجع را بتوان به طور ایمن در برنامه‌نویسی همزمان استفاده کرد، جایی که چندین فرآیند ممکن است همزمان در حال اجرا باشند.
ایجاد مراجع
مراجع با فراخوانی تابع درونی make_ref/0 تولید می‌شوند. هر فراخوانی از این تابع یک مرجع جدید تولید می‌کند که متمایز از همه مراجع دیگری است که در طول اجرای برنامه ایجاد شده‌اند. این امر حیاتی است تا اطمینان حاصل شود که مراجع را می‌توان به طور قابل اعتماد برای ردیابی منابع یا فرآیندها بدون خطر برخورد استفاده کرد.

ویژگی‌های مراجع :
منحصر به فرد بودن: هر مرجع تضمین می‌شود که در سراسر سیستم ارلنگ منحصر به فرد باشد. این بدان معناست که هیچ دو مرجعی هرگز برابر نخواهند بود، که آنها را برای تمایز بین موجودیت‌های مختلف ایده‌آل می‌کند.
ثابت بودن: یک مرجع پس از ایجاد، قابل تغییر نیست. این ثابت بودن یک ویژگی مشترک در زبان‌های برنامه‌نویسی تابعی مانند ارلنگ است.
استفاده: مراجع اغلب در سناریوهای مربوط به ارتباطات آسنکرون استفاده می‌شوند، مانند زمانی که پیام‌ها بین فرآیندها ارسال می‌شوند. آنها می‌توانند به عنوان شناسه‌هایی برای پاسخ‌ها یا ردیابی وضعیت عملیات‌ها عمل کنند.

 Binaries 
دودویی دنباله‌ای از بایت است. باینری راه صرفه جویی در فضای ذخیره‌سازی داده‌های دودویی را ارائه می‌دهد.

 Pids 
pid برای شناسایی فرایند کوتاه است. pid توسط ارقام ابتدایی ارلنگ ایجاد می‌شود.

 Ports 
Ports برای برقراری ارتباط با دنیای خارج استفاده می‌شود. پورت‌ها با function-built-in open_port ایجاد می‌شوند. پیام‌ها را می‌توان به پورت‌ها ارسال و دریافت کرد، اما این پیام‌ها باید به اصطلاح «پروتکل پورت» مطابقت داشته باشند.

 Funs 
Funs تابع بسته‌است. Funs توسط عبارات فرم ایجاد می‌شود: Fun(...) -> … end

 Tuples 
Tupels ظروف برای تعداد ثابت از انواع داده ارلنگ هستند. نحو {D1 , D2, … ,Dn} یک تابع را نشان می‌دهد که استدلال آن D1, D2, … ,Dn است. استدلال می‌تواند نوع داده‌های اولیه یا انواع داده‌های ترکیب باشد. هر عنصر یک دوره زمانی می‌تواند در زمان ثابت مشاهده شود.

 Lists 
لیست‌ها ظروف برای تعداد متغیری از انواع داده Erlang هستند. نحو [Dh | Dt] یک لیست را نشان می‌دهد که اولین عنصر آن Dh است و عناصر باقی‌مانده آن Dt است. نحو [] یک لیست خالی را نشان می‌دهد. نحو [D1، D2، ..، Dn] کوتاه است برای [D1 | [D2 | .. | [Dn | []]]]. اولین عنصر از یک لیست در زمان ثابت قابل دسترسی است. اولین عنصر از لیست، سر لیست است. باقی‌مانده از یک لیست زمانی که سر آن حذف شده‌است، دم لیست است.

 Maps 
نقشه‌ها دارای تعداد متغیری از ارتباطات کلیدی ارزش هستند. نحو به این صورت # {Key1 => Value1، …، KeyN => ValueN} است.

 Strings 
رشته‌ها مابین نقل قول دوتایی نوشته می‌شوند. این یک نحو جالب برای نمایش دنباله‌ای از کدهای اسکی یا لیستی از کارکترها می‌باشد؛ بنابراین، به عنوان مثال، رشته "CAT" به صورت [۹۹٬۹۷٬۱۱۶] کوتاه می‌شود. این پشتیبانی جزئی برای رشته Unicode است.

 Records 
سوابق یک راه مناسب برای ارتباط یک برچسب با هر یک از عناصر در یک تاپل فراهم می‌کند. این موضوع اجازه می‌دهد تا به یک عنصر از یک تاپل با نام و نه با موقعیت اشاره کرد. یک پیش کامپایلر طول می‌کشد؛ رکورد، تعریف و جایگزین آن با مرجع تاپل مناسب شود.

 بارگذاری کد و ماژول‌های جدید 
ارلنگ از بروزرسانی برنامه‌هایی با سطح زبان پویا پشتیبانی می‌کند. برای اجرای این، کد به عنوان یک واحد «ماژول» بارگذاری و مدیریت می‌شود؛ ماژول یک واحد تلفیقی است.
سیستم می‌تواند هم‌زمان دو نسخه از یک ماژول را در حافظه نگه دارد و فرایندها می‌توانند هم‌زمان هر یک از کدها را اجرا کنند. به نسخه‌ها با نسخه‌های جدید و قدیمی مراجعه می‌شود. فرایندها تا زمانی که یک تماس خارجی به ماژول آن ایجاد نشود به نسخه جدید تبدیل نمی‌شوند.

یک مثال از مکانیزم بارگیری کد:

  %% A process whose only job is to keep a counter.
  %% First version
  -module(counter).
  -export([start/0, codeswitch/1]).

  start() -> loop(0).

  loop(Sum) ->
    receive
       {increment, Count} ->
          loop(Sum+Count);
       {counter, Pid} ->
          Pid ! {counter, Sum},
          loop(Sum);
       code_switch ->
          ?MODULE:codeswitch(Sum)
          % Force the use of 'codeswitch/1' from the latest MODULE version
    end.

  codeswitch(Sum) -> loop(Sum).

برای نسخه دوم، ما امکان اضافه کردن شمارش به صفر را اضافه می‌کنیم.

  %% Second version
  -module(counter).
  -export([start/0, codeswitch/1]).

  start() -> loop(0).

  loop(Sum) ->
    receive
       {increment, Count} ->
          loop(Sum+Count);
       reset ->
          loop(0);
       {counter, Pid} ->
          Pid ! {counter, Sum},
          loop(Sum);
       code_switch ->
          ?MODULE:codeswitch(Sum)
    end.

  codeswitch(Sum) -> loop(Sum).

 منابع 

رده:ارلنگ
رده:اریکسون
رده:زبان‌های برنامه‌نویسی
رده:زبان‌های برنامه‌نویسی اعلانی
رده:زبان‌های برنامه‌نویسی پویا
رده:زبان‌های برنامه‌نویسی تطبیق الگو
رده:زبان‌های برنامه‌نویسی ساخته‌شده در ۱۹۸۶ (میلادی)
رده:زبان‌های برنامه‌نویسی ساخته‌شده در دهه ۱۹۸۰ (میلادی)
رده:زبان‌های برنامه‌نویسی ماشینی پویا
رده:زبان‌های برنامه‌نویسی هم‌روند
رده:زبان‌های تابعی
رده:نرم‌افزارها بر پایه زبان برنامه‌نویسی
رده:نرم‌افزارهای آزاد چندسکویی
رده:نرم‌افزارهای مالکیتی پیشین