Erlang (język programowania)

Z Wikipedii, wolnej encyklopedii
Skocz do: nawigacja, szukaj
Erlang
Logo języka
Logo języka
Pojawienie się 1986
Paradygmat wieloparadygmatowy: funkcyjny, współbieżny
Typowanie dynamiczne (silne)
Implementacje {{{implementacje}}}
Pochodne {{{pochodne}}}
Aktualna wersja stabilna R16B01 – 19 czerwca 2013
Aktualna wersja testowa {{{wersja testowa}}}
Twórca Ericsson
Licencja zmodyfikowana MPL
Platforma sprzętowa wieloplatformowy
Platforma systemowa wieloplatformowy
http://www.erlang.org/

Erlang jest językiem programowania zaprojektowanym z myślą o zastosowaniach współbieżnych, a także środowiskiem uruchomieniowym dla aplikacji w nim napisanych. Sekwencyjny podzbiór Erlanga jest językiem funkcyjnym z wartościowaniem zachłannym, jednokrotnym przypisaniem oraz dynamicznym typowaniem. Część współbieżna bazuje na teoretycznym modelu znanym jako Actor model. Język został zaprojektowany pod kątem tworzenia rozproszonych systemów wymagających długotrwałej pracy oraz odporności na awarie. Obsługuje mechanizm hot-swappingu pozwalający na aktualizację kodu aplikacji bez jej zatrzymywania.

Język został zaprojektowany przez Joe Armstronga w 1986 roku pracującego w firmie Ericsson. Początkowo był własnościowym narzędziem tej firmy, lecz w roku 1998 wraz z implementacją i bibliotekami, stał się oprogramowaniem open source. Nazwa Erlang została nadana na cześć A. K. Erlanga, choć często bywa również interpretowana jako ERicsson LANGuage.

Historia[edytuj | edytuj kod]

Między 1982 a 1986 rokiem w laboratoriach firmy Ericsson prowadzone były badania nad przydatnością poszczególnych istniejących wówczas języków programowania pod kątem tworzenia aplikacji współbieżnych na potrzeby telekomunikacji, które wymagały długotrwałej, bezawaryjnej pracy przy dużej liczbie wątków[1]. Analizowano cechy każdego języka, identyfikując potencjalne problemy, jakie mogły one powodować. Mimo stopniowego zawężania zbioru rozpatrywanych języków, ustalono, że żaden z nich nie spełnia wymagań firmy, dlatego zdecydowano się na zaprojektowanie zupełnie nowego języka od podstaw.

Autorem języka był Joe Armstrong, wzorując się na języku Prolog i pisząc w nim pierwszy interpreter[2]. Był on testowany przez Ericsson oraz wybrane firmy zewnętrzne. W 1990 roku język został pokazany publicznie na konferencji ISS'90, co zaowocowało wzrostem liczby użytkowników[1][2]. Pierwsza implementacja języka była mało wydajna, dlatego już w latach 80. rozpoczęto prace nad jej szybszym następcą. Ostateczne jej udostępnienie miało miejsce w roku 1991. Rok później ukazała się pierwsza książka poświęcona Erlangowi, a w 1993 Ericsson wydzielił samodzielny dział zajmujący się rozwojem i dystrybucją systemu oraz narzędzi do niego.

W 1998 roku Ericsson zademonstrował switch AXD301 z oprogramowaniem zawierającym milion linii kodu w Erlangu, który osiągnął wskaźnik niezawodności 99,9999999%, co oznaczało, że w ciągu roku system mógł mieć co najwyżej 0,0315 sekundy przestoju spowodowanego awarią. Niedługo później firma Ericsson zabroniła swoim oddziałom wykorzystywanie Erlanga w nowych produktach z uwagi na jego własnościowy charakter. Stało się to przyczyną konfliktu między Ericssonem a Armstrongiem, który wraz z zespołem opuścił firmę[2]. Pod koniec tego samego roku kod implementacji Erlanga został otwarty i udostępniony jako oprogramowanie open source. Zakaz został w późniejszych latach cofnięty, a Armstrong powrócił do pracy w Ericssonie w 2004 roku.

W 2007 roku w Erlangu pojawiła się obsługa symetrycznej wieloprocesorowości.

Założenia[edytuj | edytuj kod]

W przetwarzaniu współbieżnym największe zagrożenie dla bezpieczeństwa systemu stanowi globalny stan, który może zostać w dowolnej chwili zmieniony przez dowolny wątek. Klasyczne mechanizmy synchronizacji, takie jak muteksy i semafory, były skomplikowane w użyciu, a analiza większych systemów z nich korzystających była nieefektywna. Zamiast nich, mechanizm współbieżności w Erlangu opracowano na bazie matematycznego modelu znanego jako Actor model, który został zaprezentowany w 1975 roku. W celu eliminacji skutków ubocznych część sekwencyjną Erlanga zaprojektowano jako język funkcyjny. Ponieważ wszystkie funkcje są z założenia bezstanowe, wykonywane równolegle zadania nie współdzielą między sobą żadnych danych a zatem nie mogą przypadkowo wpłynąć na przebieg innego zadania, co najczęściej kończyłoby się awarią. Z tego powodu w Erlangu nie istnieje pojęcie wątku – wszystkie zadania są procesami.

Środowisko uruchomieniowe Erlanga zostało zaprojektowane, aby efektywnie radzić sobie z obsługą dużej liczby procesów. Wynika to nie tylko z chęci udostępnienia aplikacjom erlangowym większych zasobów, lecz także z faktu, iż konstrukcja języka zachęca programistę do tworzenia procesów w miejscu, gdzie w innych językach stosowane były mechanizmy sekwencyjne. Erlang potrafi wykorzystywać możliwości maszyn wieloprocesorowych, a także skalować aplikację na środowisko sieciowe w sposób przezroczysty – model współbieżności sprawia, że z punktu widzenia procesu nie ma różnicy między komunikacją z innym procesem uruchomionym na tym samym a na odległym węźle.

Długodziałające systemy są narażone na różnego rodzaju awarie, związane zarówno z błędami w oprogramowaniu, jak i problemami sprzętowymi. Istotnym celem Erlanga było zapewnienie możliwości obsługi sytuacji krytycznych już na poziomie języka. Środowisko uruchomieniowe raportuje wszystkie błędy jako wyjątki. Procesy mogą śledzić się nawzajem, dzięki czemu możliwe jest wykrycie awarii jednego z nich i jego ponowne uruchomienie. Dodatkowo, aby unikać przestojów, Erlang udostępnia mechanizm hot-swappingu umożliwiający aktualizację aplikacji bez jej wyłączania.

Paradygmaty programowania[edytuj | edytuj kod]

Programowanie funkcyjne[edytuj | edytuj kod]

Silnię można zaimplementować w następujący sposób:

-module(fact).
-export([fac/1]).
 
fac(0) -> 1;
fac(N) when N > 0 -> N * fac(N-1).

Poniżej jest implementacja algorytmu Quicksort

%% quicksort:qsort(List)
%% Sort a list of items
-module(quicksort).
-export([qsort/1]).
 
qsort([]) -> [];
qsort([Pivot|Rest]) ->
    qsort([ X || X <- Rest, X < Pivot]) ++ [Pivot] ++ qsort([ Y || Y <- Rest, Y >= Pivot]).

Powyższy przykład wywołuje rekursywnie funkcje qsort dopóki nie ma już więcej elementów do posortowania. Wyrażenie [ X || X <- Rest, X < Pivot] można przeczytać jako "Dla wszystkich X należących do Rest, takich że X jest mniejsze od Pivot", co bardzo upraszcza obsługę list.

Model współbieżności[edytuj | edytuj kod]

Główną siłą Erlanga jest wsparcie dla współbieżności. Ma on mały, lecz bardzo potężny zbiór niskopoziomowych funkcji do tworzenia procesów i komunikacji między nimi. Procesy są podstawowymi elementami w strukturze aplikacji napisanych w Erlangu. Należy zaznaczyć, iż Erlang nie używa ani procesów systemu operacyjnego, ani wątków. Procesy Erlanga są lekkimi wątkami podobnymi do zielonych wątków. Dzięki temu można utworzyć ich bardzo dużo bez zmniejszania wydajności (przeprowadzano testy wydajnościowe z 20 milionami procesów[3]).

Komunikacja pomiędzy procesami w Erlangu odbywa się poprzez asynchroniczne kanały (procesy nie współdzielą żadnych zmiennych) – system wymiany wiadomości: każdy proces w Erlangu ma skrzynkę (ang. mailbox), w której są przechowywane wiadomości wysłane przez inne procesy, dopóki nie zostaną odczytane. Proces Erlanga następnie używa instrukcji receive do pobrania wiadomości. Odbieranie wiadomości odbywa się przez mechanizm dopasowania wzorca. Po odczytaniu wiadomości proces Erlanga wraca do wykonywania. Dowolna struktura w Erlangu może zostać użyta jako wiadomość – prymitywy (liczby całkowite, zmiennoprzecinkowe, znaki, atomy), krotki, listy, a nawet funkcje.

Przykładowy kod:

 Pid = spawn(Mod, Func, Args)       % uruchamia funkcje Func jako nowy proces
 Pid = spawn(Node, Mod, Func, Args) % uruchamia funkcje Func na zdalnym węźle Node
 
 Pid ! a_message      % wysyła wiadomość do procesu (asynchronicznie)
 
 receive       % odbiera wiadomość wysłaną do tego procesu
   a_message -> do_something;
   {data, Data_content} -> do_something_else(); % To jest 2-ka składają się z atomu i pewnych danych
   {hello, Text} -> io:format("Got hello message: ~s", [Text]);
   {goodbye, Text} -> io:format("Got goodbye message: ~s", [Text])
 end.

Prosty serwer można zaimplementować na bazie prostej pętli:

-export([start/1, loop/1, net_state/2, get_state/1]).
 
start(S) ->
  Pid = spawn(mymodule, loop, [S]). % uruchom proces serwera
 
% kod wykonywany po stronie serwera
 
loop(State) ->
  receive
    {mymodule, get_state, Pid, Ref} -> Pid ! {mymodule, state, Ref, State}, loop(State);
    {mymodule, new_state, Pid, Ref, State2} -> Pid ! {mymodule, ok, Ref}, loop(State2);
    upgrade -> mymodule:loop(State);
    M -> io:format("Niezrozumiala wiadomosc: ~p~n", [M]), loop(State)
    after 1000 -> io:format("Nic sie nie dzieje~n"), loop(State)
  end.
 
% Kod wykonywany po stronie klienta
 
new_state(Pid, X) ->
  Ref = make_ref(), % stworzy unikalna wartosc, aby nie pomylic sie przy odbiorze
  Pid ! {mymodule, new_state, self(), Ref, X},  % wyslij wiadomosc
  rec1(Ref). % zacznij odbierac, potencjalnie usuwajac stare (po timeoutach) wiadomosci
 
rec1(Ref) ->
  receive
    {mymodule, ok, Ref, OldState} -> ok  % czekaj na dokladnie nasza wiadomosc, jesli jej nie ma, to:
    {mymodule, ok, OtherRef, _OldState} -> rec1(Ref); % usun stare wiadomosci z kolejki i czekaj nadal na odbior, jesli ich nie ma, to:
    after 1000 -> throw (timeout) % w przypadku timeoutu, zglos wyjatek
  end.
 
...

(make_ref/0 zwraca unikalną wartość, dzięki czemu nawet przy przekroczeniu czasu oczekiwania i przyjściu starej wiadomości selektywny receive nie pomyli nowej odpowiedzi ze starą)

W większości wypadków korzysta się z wytycznych projektowych OTP, wśród których istnieje zachowanie (behaviour) gen_server, ułatwiające pisanie wydajnych i bezpiecznych serwerów.

W Erlangu jest wbudowane wsparcie dla procesów rozproszonych. Proces może zostać utworzony na zdalnym węźle, a komunikacja z nim jest przezroczysta (tzn. komunikację ze zdalnym procesem odbywa się w dokładnie taki sam sposób jak z procesem lokalnym).

Współbieżność wspiera obsługę błędów w Erlangu. Kiedy proces się zepsuje, kończy się i wysyła wiadomość do procesu kontrolnego, który może podjąć odpowiednią akcje. Ten sposób naprawy błędów ułatwia obsługę i redukuje złożoność kodu.

Dystrybucja[edytuj | edytuj kod]

Erlang został upubliczniony wraz z kodem źródłowym przez firmę Ericsson, aby zapewnić jego niezależność od pojedynczej firmy i zwiększyć popularność języka. Język jest rozprowadzany razem z bibliotekami (m.in. implementacją CORBA, SNMP, HTTP, FTP, TCP/IP, IIOP) oraz rozproszoną bazą danych czasu rzeczywistego (Mnesia) całość jest znana jako Open Telecom Platform (OTP), ponieważ jest najczęściej wykorzystywana w zastosowaniach telekomunikacyjnych. Ericsson i kilka innych firm oferują komercyjną pomoc dla Erlanga.

Ważnym elementem OTP są gotowe wzorce projektowe (tzw. zachowania – behaviors) do tworzenia aplikacji, systemów nadzoru procesów, czy serwerów i mechanizmów przetwarzania zdarzeń.

Po uwolnieniu źródeł w 1998, jest coraz chętniej wykorzystywany w zastosowaniach współbieżnych (oprogramowanie serwerowe) przez duże światowe koncerny[4]. Największym użytkownikiem jest Ericsson, zaś wśród innych można wymienić Facebook, T-Mobile czy Goldman Sachs. Nie jest to jednak język ogólnego przeznaczenia – używający go programiści zwracają uwagę na wiele niedoskonałości w innych obszarach zastosowań[5].

Erlang jest aktywnie rozwijany z regularnymi wydaniami. Najnowsze wydanie (R15B) dostępne jest od grudnia 2011 dla systemów Unix oraz Microsoft Windows[6].

Dostępny jest również interfejs niskopoziomowy dla języków C i Java. Istnieją również biblioteki ułatwiające obsługę protokołu i wartości erlangowych z poziomu C[7] czy Pythona[8].

Corocznie odbywa się kilka konferencji poświęconych Erlangowi: Erlang Factory w San Franciso i Londynie, Erlang eXchange w Londynie, Erlang/OTP User Conference w Sztokholmie, ACM SIGPLAN Erlang Workshop w Edynburgu.

Zobacz też[edytuj | edytuj kod]

Przypisy

  1. 1,0 1,1 History of Erlang (ang.). An Erlang Course. [dostęp 2010-09-18].
  2. 2,0 2,1 2,2 Joe Armstrong: A History of Erlang (ang.). [dostęp 2010-09-18].
  3. stress-testing erlang (ang.). Grupa dyskusyjna comp.lang.functional. [dostęp 28-08-2011].
  4. Who uses Erlang for product development? (ang.). Erlang FAQ. [dostęp 2011-11-19].
  5. The Trouble with Erlang (or Erlang is a ghetto) (ang.). Unlimited Novelty, 2011-07-26. [dostęp 2011-11-19].
  6. R15B a new major release (ang.). [dostęp 2011-12-30].
  7. DryverlErlang-to-C binding "assembly language" (ang.)
  8. Pytherl na Bitbucket

Linki zewnętrzne[edytuj | edytuj kod]