Защо да учим и използваме Elixir?


Това е блог пост към първата лекция1 от курса Функционално програмиране с Elixir, провеждан във ФМИ през летния семестър на 2018/2019 година. В него ще отговорим на въпроса защо бихте учили и използвали Elixir. Но първо малко предистория.

Erlang

Erlang е функционален език, разработен в средата на 80-те години от Ериксон, с цел писане на телеком програми. Въпреки че мотивацията за създаването му е водена от спецификата на сферата на телекомуникациите, Erlang не се използва само в тази област. Eдна от по-рядко споменаваните причини2 за създаването му е желанието да се заменят използваните дотогава специализиран хардуер и софтуер (включително и операционна система). Erlang няма експлицитна поддръжка за програмиране на телефони или каквото и да е било друго телеком оборудване. Няма и изисквания за специален хардуер и операционна система. Вместо това езикът предлага решения за техническите изисквания и проблеми, срещани при създаването на подобен тип софтуер:

  • конкурентност;
  • скалируемост;
  • дистрибутираност;
  • толерантност към грешки;
  • обновления без спиране на програмата;
  • бързо отговаряне на всички заявки дори при високо натоварване;

Всичко това се случва във време, когато интернет не е широко разпространен и повечето програми работят на един компютър и без връзка с интернет. При този вид софтуер няма изисквания за дистрибутираност и хоризонтална скалируемост. По това време персоналните компютри не са разполагали и с 2-, 4- или 16-ядрени процесори - реално изискване софтуерът автоматично да започне да работи по-бързо при добавяне на още процесори/ядра не е съществувало. Директни следствия от това са дизайнът и предназначението на останалите програмни езици, разработени по това време или по-рано, както и езиците, базирани на тях.

Дори никога да не използвате Erlang, то идеите и подходът3 му към решаване на определен тип проблеми са напълно приложими при използването на други езици.

Къде е мястото на Erlang днес?

Добре, но колко от нас пишат софтуер за телекоми или софтуер с подобни изисквания? Всъщност доста от нас. Изискванията към съвременните уеб приложения се припокриват напълно с изискванията, с които са се съобразили създателите на Erlang. Голямо предимство е да имаш език и платформа, които са изградени на база задоволяване на тези изисквания, без нуждата от външни библиотеки, които да имплементират липсващата функционалност в езика и които заобикалят неговите недостатъци.

Ad-hoc Erlang implementation

Ако искате да разберете повече за гаранциите, които ни дава BEAM4 - виртуалната машина, върху която се изпълнява Erlang, - то най-бързият начин е да изгледате това видео.

Elixir

Защо говорим толкова за Erlang в статия, която носи името “Защо да учим и използваме Elixir?Best part of Elixir tweet

Elixir е функционален език. Разработката му започва през 2011 г., а версия 1.0 се появява през септември 2014 г.

Elixir се изпълнява върху BEAM. Той може да използва всичко вече написано, както и всичко, което ще бъде написано на Erlang. Това ни дава възможността да съчетаваме нов и модерен език с библиотеки, издържали теста на времето. Извикването на Erlang код от Elixir не носи допълнително забавяне и нужда от използване на криптичен синтаксис или преобразувания на типове. Нека сравним разликите на извикване на Elixir и Erlang функция от даден модул:

Elixir:

DateTime.utc_now()

Erlang:

:crypto.strong_rand_bytes(64)

Elixir модулите започват с главна буква, а Erlang модулите започват с :и малка буква.

Нека да разгледаме една малка част от нещата, заради които ние харесваме Elixir/Erlang:

  • Функционален език - непроменими (immutable) и персистентни (persistent) структури от данни, съпоставяне на образци (pattern matching), функции от по-висок ред, композиция на функции.
  • Баланс между чисти (pure) и функции със странични ефекти. Тук някои от заклетите фенове на Haskell може да не се съгласят. Но някои неща трябва да бъдат пожертвани на олтара на продуктивността.
  • Процеси на ниво език - може би звучи скучно, но това е основата, на която се изгражда толкова известната конкурентност и дистрибутираност на Erlang/Elixir.
  • OTP (Open Telecom Platfom) - това е платформа, която вече не се използва само за писане на телеком програми, а на софтуер, който има същите изисквания. Както споменахме по-горе, такива всъщност са доста от приложенията в ерата на интернет. По време на курса ще разгледаме част от библиотеките, които OTP предоставя. Засега повече информация може да намерите тук.

Грешно е да смятаме Elixir за конкурент, който ще убие Erlang. Напротив, Elixir е едно от най-хубавите неща, които можеше да му се случат. Erlang, който е неговата солидна основа, търпи все по-бурно развитие в следствие на интереса към Elixir и прииждането на нови хора в общността.

Но за да се появи Elixir и да правим курс за него, а не за Erlang, то той трябва да поставя нещо ново на масата.

  • Elixir е Erlang. Всичко, което е плюс на Erlang, е плюс и на Elixir.
  • Но Elixir е и нещо повече.
  • По-добри инструменти в сравнение с Erlang.
  • Хубава документация. Създателят на езика твърди, че грешки в документацията трябва да се третират като грешки в самата програма.
  • Зад езика и неговата екосистема стоят опитни, отзивчиви и интелигентни хора.
  • Удобен и красив синтаксис. Erlang има минималистичен синтаксис, дори прекалено. Това води до доста boilerplate и повторения в кода. Липсата на макроси подчертава този проблем.
  • Мощни макроси. За разлика от тези в С/С++, макросите в Elixir не работят върху низове, ами върху AST (Abstract Syntax Tree). Макросите в Elixir са повече повлияни от тези в Lisp и Clojure.
  • Полиморфизъм чрез протоколи.
  • Качествени библиотеки. Доста библиотеки са написани на Erlang и са използвани дълго време, за да твърдим, че са стабилни и добре тествани. Но също така има доста библиотеки, написани сравнително наскоро на Elixir. Това има предимството много от грешките, направени в по-стари библиотеки в други езици да бъдат избегнати. Примери за такива нови библиотеки са: Plug, Ecto, Phoenix, GenStage и много други.
  • Pipe оператор |>. С негова помощ кодът е безспорно по-красив, удобен, четим, лесен за писане и за промяна. Едно скрито предимство на това е консистентността, която той вкарва в стандартната библиотека на езика. За да e по-лесно използването на |>, е прието функциите да приемат като първи аргумент данните, върху които работят.

Нека разгледаме един пример за разликата между код, който не използва |> и код, който използва |>.

Целта е да извършим поредица от трансформации върху списък от числа.

Един начин да напишем това е:

data = [1,2,3,4,5]
data_squared = Enum.map(data, fn n -> n*n end)
data_filtered = Enum.filter(data_squared, fn n -> n >10 end)
sum = Enum.reduce(data_filtered, 1, &(&1+&2))

Ами ако не искаме да използваме толкова много временни променливи? Можем да вложим функциите:

Enum.reduce(Enum.filter(Enum.map([1,2,3,4,5], fn n -> n*n end),fn n ->n > 10 end), 1, &(&1 + &2))

В този случай четимостта клони към нула, а добавянето на нова трансформация не е никак лека задача.

Тук идва на помощ |>. Той подава резултата от лявата си страна като първи аргумент на израза в дясната си страна. Нищо повече, нищо по-малко, но достатъчно, за да можем да напишем нашия код по следния начин:

result =
  [1, 2, 3, 4, 5]
  |> Enum.map(fn n -> n * n end)
  |> Enum.filter(fn n -> n > 10 end)
  |> Enum.reduce(1, &(&1 + &2))

Ами лошите страни на Erlang/Elixir?

За да не се изреждат само суперлативи за езика, е редно да споменем и някои от не толкова хубавите му страни. Някои от тях са в този списък само защото изглеждат странно на пръв поглед, но всъщност са полезни и с течение на времето ще разберем защо.

  • Липсата на библиотеки, налични в много останали езици. Тъй като Elixir е нов език, а Erlang няма популярността на Java/Python/Ruby, то понякога ще се случва да няма библиотеката, която очаквате. Понякога ще се случва да има единствено Erlang библиотека, която без проблеми може да използвате, но ще трябва да научите и малко Erlang, ако искате да четете кода ѝ.
  • Заблудата, породена от изказвания на хора, незапознати с езика. Често срещано оплакване е, че синтаксисът около конкурентността не е толкова прост и минимален, както в Go. Това е така, защото конкурентността в Elixir решава проблеми, свързани с high availability, докато в Go се използва чисто и просто за конкурентността.
  • На пръв поглед не е очевидно къде се намират някои функции. Ако искате да намерите дължината на списък, то функцията в модула List ли се намира? Всъщност откривате, че няма нито List.size, нито List.length. Дължината се намира с Enum.count, която вътрешно използва :erlang.length (достъпна и като Kernel.length или просто length). Но с Enum.count можем да намерим и броя елементи на всичко, което имплементира протокола Enumerable.

Проблемът с библиотеките е проблем на всеки език на този етап от развитието си. Нека уточним: тук не говорим за важни библиотеки - HTTP сървър/клиент, библиотеки за работа с бази данни, уеб фреймуърк, JSON декодери; такива библиотеки има, и то доста добри. Става въпрос за малките неща. Това не е проблем на език или платформата и е поправим, макар и бавно. На курса по Elixir във ФМИ ще даваме бонус точки за принос към някоя библиотека с отворен код. Още по-добре, ако създадете нова.

Източници:

[1] Цветинов, Николай (Meddle). Функционално програмиране с Elixir. Gitpich, 18.02.2019. Available from: https://gitpitch.com/ElixirCourse/presentations-2019/?p=welcome [cited 22.02.2019].

[2] Williams, Mike. The True story about why we invented Erlang and A few things you don’t want to tell your Manager. Erlang Factory, 26.02.2011. Available from: https://www.erlang-factory.com/upload/presentations/416/MikeWilliams.pdf [cited 22.02.2019].

[3] Hebert, Fred. The zen of Erlang. Ferd, 08.02.2016. Available from: https://ferd.ca/the-zen-of-erlang.html [cited 22.02.2019].

[4] Virding, Robert. Hitchhiker’s Tour of the BEAM. Erlang Factory, 2012. Available from: http://www.erlang-factory.com/upload/presentations/708/HitchhikersTouroftheBEAM.pdf [cited 22.02.2019].

Jurić, Saša. ElixirDaze 2017- Solid Ground by Saša Juric. YouTube, 16.03.2017. Availalble from: https://www.youtube.com/watch?v=5SbWapbXhKo [cited 22.02.2019].

Официален сайт на Erlang

Официален сайт на Elixir