Erlang
| Erlang | |
|---|---|
| Парадигма | функційна, конкурентна, розподілена |
| Дата появи | 1986 |
| Творці | Джо Армстронг, Роберт Вірдінг, Майк Вільямс |
| Розробник | Ericsson, спільнота розробників |
| Останній реліз | 29.1.2 (14 жовтня, 2026) |
| Система типізації | динамічна, сильна |
| Під впливом від | Prolog, Smalltalk, Lisp, PLEX |
| Вплинула на | Elixir, Akka |
| Мова реалізації | C |
| Операційна система | багатоплатформова |
| Ліцензія | Apache License 2.0 |
| Звичайні розширення файлів | .erl, .hrl, .beam |
| Репозиторій вихідного коду | github |
| Вебсайт | www |
Erlang (англійська вимова /ˈɜːrlæŋ/; українською — Ерланг) — мова програмування загального призначення з функційною парадигмою та динамічною типізацією. Її розроблення розпочалося 1986 року в дослідницькій лабораторії Ericsson для створення телекомунікаційних систем. Характерні риси Erlang — легкі ізольовані процеси, асинхронний обмін повідомленнями, засоби розподіленого виконання та побудови відмовостійких програм.[1][2]
У Erlang конкурентність закладено в модель виконання: незалежними процесами керує Erlang Run-Time System (ERTS), а не окремі процеси операційної системи. Програмні модулі зазвичай компілюються у файли .beam, інструкції яких виконує віртуальна машина BEAM у складі ERTS. Сучасні випуски підтримують JIT-компіляцію на відповідних апаратних платформах. Мова, середовище виконання, стандартні бібліотеки, інструменти й правила проєктування разом утворюють платформу Erlang/OTP (історично англ. Open Telecom Platform).[3][4]
Erlang застосовують у телекомунікаційних платформах, серверних службах, базах даних та системах обміну повідомленнями, насамперед там, де важливі тривала робота, конкурентна обробка запитів і відновлення після часткових збоїв. Водночас сама мова не гарантує безперервності роботи: надійність визначають також архітектура застосунку, якість коду, керування станом і зовнішні залежності.[5][6]
1986 року в Ericsson Computer Science Laboratory Джо Армстронг, Роберт Вірдінг і Майк Вільямс досліджували мови та інструменти для побудови програмного забезпечення телефонних комутаторів. Перші прототипи Erlang реалізували засобами Prolog: це дозволяло швидко експериментувати із синтаксисом, зіставленням зі взірцем і взаємодією процесів. До кінця 1980-х років основні рішення щодо мови сформувалися.[7][6]

Назва Erlang одночасно відсилає до Агнера Крарупа Ерланга, основоположника теорії масового обслуговування, та до гри слів ERicsson LANGuage. Учасники розробки підтверджували цю подвійність походження назви. Мову не слід плутати з ерлангом — одиницею телекомунікаційного навантаження.[8][2]
Для практичної експлуатації початкова реалізація на Prolog була надто повільною. 1989 року з'явилася абстрактна машина JAM (англ. Joe's Abstract Machine), реалізована переважно мовою C. Пізніше експериментували з TEAM — трансляцією Erlang у C — та створили віртуальну машину BEAM, призначену для виконання компактного скомпільованого коду. Ранні варіанти BEAM суттєво змінювалися, перш ніж стало можливим стабілізувати формат її модулів.[9]
Важливими джерелами ідей для Erlang були логічне програмування Prolog, обмін повідомленнями незалежних процесів та практики розробки систем, які повинні працювати під час оновлення окремих компонентів. Із середини 1990-х років Erlang дедалі більше використовували в реальних продуктах Ericsson, зокрема завдяки інструментам OTP, покликаним стандартизувати запуск, контроль і оновлення багатокомпонентних систем.[7][6]
У 1996 році вийшов перший випуск OTP R1B. Платформа поєднувала середовище виконання та прикладні бібліотеки й поступово перетворила Erlang з окремої мови на основу для розроблення великих систем. 1998 року Ericsson оприлюднила вихідний код Erlang/OTP. Поширення за межами компанії підтримали незалежні розробники, навчальні матеріали, дослідницькі групи та компанії, які використовували Erlang у власних продуктах.[9][7][1]
Спочатку відкриті випуски використовували Erlang Public License, створену на основі Mozilla Public License. Починаючи з OTP 18.0 (2015), вихідний код поширюють за Apache License 2.0.[10]
Один із довготривалих напрямів розвитку Erlang/OTP — масштабування на багатоядерних комп'ютерах: від підтримки SMP у 2006 році до перероблення планувальників і системи пам'яті. Інший — удосконалення компілятора: від введення Core Erlang до проміжного представлення SSA та JIT-компілятора BeamAsm, описаних докладніше у статті про BEAM. Наукові дослідження показували, що зі зростанням числа процесорних ядер і вузлів розподіленої системи з'являються нові вузькі місця, які потребують архітектурних змін.[11][9]
Випуски Erlang/OTP відображають зміни не лише синтаксису Erlang, а й віртуальної машини BEAM, системи виконання ERTS, стандартних бібліотек та інструментів розробки. У старій схемі назви мали вигляд R11B чи R16B, а починаючи з OTP 17.0 (2014) використовують цифрові версії на зразок 28.1.2. Їхні основні частини позначають головні зміни, функціональні оновлення та виправлення; додаткові числові частини можливі в окремих гілках супроводу. Кожний застосунок OTP, наприклад kernel або stdlib, має також власну версію.[12]
Наведено основні історичні випуски від початку платформи до OTP 29, без переліку кожного виправлення. Для розуміння того, які зміни стосувалися саме синтаксису Erlang, а які — ERTS чи OTP, подальші етапи потрібно читати з урахуванням усіх компонентів. Для раннього періоду збережена документація неоднакова за повнотою: там, де точна дата або окреме нововведення недостатньо підтверджені, подано лише загальний період і документовану тенденцію, а не припущення.
| Випуск | Дата або період | Основні зміни та значення |
|---|---|---|
| R1B | 1996 | Перший випуск OTP, що започаткував промислову платформу Erlang із бібліотеками й інструментами для побудови великих систем; у наступних релізах пріоритетом стала стабілізація BEAM.[9] |
| R2–R3 | кінець 1990-х | Продовження ранньої серії OTP R1–R5, протягом якої розробники оптимізували продуктивність компілятора й інтерпретатора BEAM, зокрема поступово відходили від генерації коду мовою C. Наявна ретроспектива не прив'язує кожну зміну окремо до R2 чи R3.[9] |
| R4 | кінець 1990-х | Перероблення завантажувача модулів BEAM: частину оптимізацій перенесено з компілятора у завантажувач, що зменшило залежність формату скомпільованого коду від внутрішніх змін реалізації. Датування цієї зміни в ретроспективі розробника наведено як приблизне.[9] |
| R5B | кінець 1990-х | Стабілізація нового формату файлів BEAM; остання серія з підтримкою старої віртуальної машини JAM. Формат файлів BEAM став основою подальшої сумісності модулів.[9] |
| R6B | близько 2000 | Перехід до нового компілятора з проміжним представленням Kernel Erlang; JAM більше не підтримувалася, а виконання зосередили на BEAM.[9] |
| R7B | 2000 | Запроваджено Core Erlang як проміжну форму компіляції, синтаксис для бітових послідовностей, інструмент перехресного аналізу xref та поліпшення роботи з мережевими сокетами.[13][9] |
| R8B | 2001 | Удосконалено багатопотокове введення-виведення, керування пам'яттю і продуктивність таблиць ETS/DETS та Mnesia; до складу OTP додано реалізацію протоколу Megaco/H.248 та дослідницький нативний компілятор HiPE як окремий застосунок. У мові запроваджено оператори короткого обчислення andalso та orelse.[14][15] |
| R9B | 2002 | Подальший розвиток засобів нативної компіляції HiPE, включеного до дистрибутиву ще в OTP R8, а також інструментів спостереження та налагодження.[16][15] |
| R10B | 2004 | Розвиток компілятора, зокрема інструкцій для конструкції try/catch і роботи з бінарними даними; основні архітектурні зміни наступної серії пов'язані вже з SMP.[17][18] |
| R11B | 2006 | Додано підтримку SMP: декілька планувальників процесів Erlang отримали можливість працювати в різних потоках операційної системи.[18] |
| R12B | 2007 | Бітові рядки (bitstrings) і бінарні генератори стали повноцінною частиною мови; на багатопроцесорних машинах SMP-емулятор почали запускати за замовчуванням.[19] |
| R13B | 2009 | Подальша робота над багатоядерним плануванням; у випуску R13B03 повідомлено про щоденне оновлення публічного репозиторію на GitHub та експериментальні нативні функції (NIF).[20] |
| R14B | 15 вересня 2010 | Перероблено внутрішню бібліотеку потоків ethread, зокрема додано оптимізовані для читання блокування, що поліпшували конкурентний доступ до таблиць ETS з параметром {read_concurrency, true}. Продовжено оптимізацію масштабованості середовища виконання.[21] |
| R15B | 14 грудня 2011 | Додано номери рядків і назви файлів у трасування винятків, об'єднано інструменти спостереження в новому інтерфейсі observer, розширено підтримку 64-бітної Windows.[22] |
| R16B | 27 лютого 2013 | Перероблено внутрішню таблицю процесів, керування чергами планувальників і портами; поліпшено завантаження коду без блокування, додано підтримку UTF-8 у вихідних файлах.[23] |
| 17.0 | 9 квітня 2014 | У мові з'явилися експериментальні maps — асоціативні масиви з доступом за ключем. Водночас представлено нову схему версіонування та експериментальну підтримку окремих планувальників для тривалих або блокувальних операцій (dirty schedulers).[24] |
| 18.0 | 24 червня 2015 | Erlang/OTP перейшла з Erlang Public License на Apache License 2.0. У системі виконання з'явився новий інтерфейс роботи з часом і режими корекції часу (time warp), призначені, зокрема, для коректнішої роботи за змін системного годинника.[25] |
| 19.0 | 22 червня 2016 | Додано поведінку gen_statem для реалізації скінченних автоматів, розширено підтримку maps у засобі статичного аналізу Dialyzer, удосконалено трасування та механізми виконання блокувальних нативних операцій.[26] |
| 20.0 | 21 червня 2017 | Для системи виконання з підтримкою SMP закріплено використання dirty schedulers, які дають змогу відокремлювати потенційно тривалі операції від звичайного планування процесів. Розширено підтримку символів Unicode в атомах та вдосконалено механізми пам'яті й роботи з таблицями ETS.[27] |
| 21.0 | 20 червня 2018 | Запроваджено нову систему журналювання logger, поліпшено масштабованість введення-виведення та оптимізовано файлові операції. Також припинено підтримку варіанта віртуальної машини без SMP.[28] |
| 22.0 | 14 травня 2019 | Компілятор переведено на проміжне представлення у формі SSA (static single assignment), що розширило можливості оптимізації. З'явився експериментальний низькорівневий модуль socket і вдосконалення масштабованості розподіленого обміну повідомленнями.[29] |
| 23.0 | 13 травня 2020 | Додано erpc — нові засоби віддалених викликів із точнішим розрізненням результатів і помилок та поліпшеною масштабованістю. Розширено можливості розподіленого запуску процесів; TLS 1.3 увійшов до переліку протоколів, підтримуваних за замовчуванням, натомість підтримку SSL 3.0 вилучено.[30][31] |
| 24.0 | 12 травня 2021 | Представлено BeamAsm — JIT-компілятор, який під час завантаження перетворює інструкції BEAM на машинні інструкції для підтримуваних 64-бітних процесорів x86. Це стало істотною зміною способу виконання скомпільованих програм Erlang.[32][33] |
| 25.0 | 18 травня 2022 | Додано експериментальний вираз maybe, який спрощує послідовності зіставлень і перевірок без глибоко вкладених конструкцій case. JIT-компілятор отримав підтримку 64-бітної архітектури ARM; також удосконалено паралельний доступ до таблиць ETS.[34] |
| 26.0 | 16 травня 2023 | З'явилися генератори для побудови maps (map comprehensions). У Dialyzer додано тип dynamic() і режим інкрементального аналізу. Значно розширено можливості інтерактивної оболонки Erlang та змінено початкові налаштування перевірки цифрових сертифікатів для TLS-клієнтів.[35] |
| 27.0 | 15 травня 2024 | Запроваджено нові засоби документування безпосередньо у вихідному коді, багаторядкові літерали та сигіли (sigils). До стандартної бібліотеки додано модуль json для роботи з JSON. Конструкцію maybe увімкнено за замовчуванням, а JIT отримав підтримку збирання даних про покриття коду.[36] |
| 28.0 | 21 травня 2025 | Додано підтримку пріоритетних повідомлень між процесами, суворих генераторів (strict generators) і паралельних генераторів (zip generators). У системі типів з'явилися іменовані типи (nominal types), які дають змогу відрізняти типи з однаковою структурою під час статичного аналізу.[37] |
| 29.0 | 13 травня 2026 | Представлено експериментальні нативні записи (native records) — окремий тип даних, на відміну від традиційних записів на основі кортежів, а також генератори, здатні повертати кілька значень за ітерацію. Додано охоронну функцію is_integer/3, лівоасоціативне застосування функцій на кшталт f(X)(Y) та попередження компілятора щодо небезпечних викликів; посилено початкові налаштування SSH й додано пріоритетну підтримку гібридного постквантового обміну ключами для TLS.[38] |
Зміни Erlang/OTP мають різну природу. Наприклад, maps та maybe розширили виражальні засоби самої мови, тоді як SMP, багаточергове планування і BeamAsm змінили переважно спосіб виконання програм. Тому номер випуску платформи не слід сприймати як номер редакції лише синтаксису Erlang.[12][11]
Після основного випуску виходять проміжні оновлення з виправленнями та вдосконаленнями. Станом на 21 жовтня 2026 року найновіший опублікований випуск — Erlang/OTP 29.1.2 від 14 жовтня 2026 року; його зміни відображені в офіційних примітках до випуску.[39] Для всіх проміжних оновлень існує офіційний покажчик версій.
Серед технічних нововведень зручно відрізняти мовні конструкції, які стають доступні програмісту, від змін у компіляторі та системі виконання. Наприклад, у серії R7B удосконалили запис двійкових послідовностей, тоді як запровадження підтримки SMP у R11B насамперед змінювало спосіб виконання вже написаних програм.[13][18]
У OTP 17 мова отримала експериментальні карти (maps), а в OTP 18 виконання операцій над великими картами оптимізували завдяки внутрішньому представленню HAMT. У OTP 19 з'явилася поведінка gen_statem, але вона належить до бібліотек OTP, а не до нового синтаксису Erlang. OTP 20 розширила допустимі символи Unicode в іменах атомів і можливості роботи з картами.[24][25][26][27]
У OTP 21 з'явилися макрос ?OTP_RELEASE та препроцесорні директиви -if і -elif, що спростило умовну компіляцію для різних випусків. OTP 23 дозволила підкреслення в числових літералах, зокрема 1_000_000, та ширше використання охоронних виразів під час зіставлення з двійковими даними й картами. У OTP 25 запровадили механізм вибіркового увімкнення нових мовних можливостей і експериментальний вираз maybe, який за замовчуванням став доступним із OTP 27.[28][40][34][36]
У OTP 26 з'явилися генератори карт, а OTP 27 додала багаторядкові рядкові літерали та сигіли. OTP 28 розширила синтаксис генераторів суворими й паралельними формами, підтримала літерали дійсних чисел у різних системах числення й дала змогу використовувати іменовані типи в засобах статичного аналізу. OTP 29 доповнила мову експериментальними нативними записами, генераторами з кількома результатами, охоронною функцією is_integer/3 і лівоасоціативним викликом функцій. Оскільки частина цих можливостей спочатку експериментальна, їхня доступність залежить від випуску й параметрів компіляції.[35][36][37][38][41]
Комплексну історію версій і змін у стандартних бібліотеках наведено у статті про OTP, історію компілятора та JIT — у статті про BEAM, розвиток планувальників, пам'яті й процесів — у статті про ERTS.
Основною одиницею виконання в Erlang є процес Erlang — легка сутність, якою керує середовище ERTS. Він має власний контекст виконання, поштову скриньку та простір пам'яті для звичайних термів. Процеси створюють функції spawn і spawn_link, а посилаються на них за ідентифікаторами типу pid. Їхня кількість може бути значно більшою, ніж число потоків операційної системи.[42][43]
Обмін даними між процесами зазвичай відбувається через асинхронні повідомлення: оператор ! надсилає повідомлення, а конструкція receive вибирає з поштової скриньки повідомлення, що відповідає одному з описаних взірців. Надсилання повідомлення не означає ані завершення обробки, ані гарантії доставки на віддалений вузол. За потреби застосунок реалізує підтвердження, контроль часу очікування і повторні спроби.[42]

Процеси Erlang ізольовані, але формулювання «Erlang взагалі не має спільної пам'яті» було б неточним. Віртуальна машина надає, зокрема, таблиці ETS, якими можуть користуватися різні процеси; також доступна інтеграція з кодом інших мов. Модель Erlang близька до моделі акторів, проте її конкретні правила доставки, обробки повідомлень і контролю помилок визначає сама платформа.[44][42]
Конкурентність означає організацію декількох незалежних потоків роботи, тоді як паралельність — їхнє фактичне виконання одночасно на декількох ядрах. Програма Erlang може бути конкурентною і на одноядерній машині; для паралельного виконання ERTS використовує декілька планувальників.[18]
Erlang дозволяє створювати зв'язки (links) та монітори (monitors) між процесами. Зв'язок передає сигнал про завершення пов'язаного процесу й, залежно від типу завершення та налаштувань, може призвести до припинення іншого процесу. Монітор дає змогу спостерігачеві отримати повідомлення 'DOWN' про завершення підконтрольного процесу, не пов'язуючи їхні життєві цикли безпосередньо.[42]
Підхід, який часто описують словами «let it crash» («нехай зазнає збою»), передбачає, що неочікувану внутрішню помилку окремого робочого процесу можна опрацювати на рівні системи нагляду: завершити несправну одиницю роботи, а тоді відновити її або пов'язану групу процесів у визначеному порядку. Він не є закликом ігнорувати перевірку введених даних, помилки прикладної логіки чи цілісність даних.[5][6]
Erlang створювали для систем, чутливих до затримок, тому віртуальна машина використовує планування з витісненням і прагне не допускати, щоб довге обчислення одного процесу нескінченно затримувало інших. Це робить Erlang придатним для багатьох завдань м'якого реального часу, проте не встановлює гарантованої верхньої межі затримки для кожної операції, як у системах жорсткого реального часу.[1][42]
Процеси Erlang можуть виконуватися на різних вузлах (nodes), які спілкуються через механізми розподіленого Erlang. У межах мережі процеси можуть обмінюватися повідомленнями, створювати монітори й зв'язки та використовувати віддалені виклики. Це спрощує побудову сервісів, розміщених на кількох комп'ютерах, але не усуває мережевих затримок, втрат з'єднання або проблеми узгодження стану після розділення мережі.[45][11]
Система Erlang підтримує оновлення завантажених модулів під час роботи, або гарячу заміну коду. Вона може певний час зберігати стару й нову версії одного модуля, дозволяючи керовано переводити процеси на новий код. Це не означає, що будь-яке оновлення відбувається автоматично або без ризику: зміни формату стану, взаємодії модулів та порядку оновлення потрібно передбачати в застосунку. OTP надає для цього додаткові механізми версій застосунків і сценаріїв оновлення.[3][46]
Erlang — функційна мова з строгим порядком обчислення (eager evaluation), динамічною типізацією та одноразовим зв'язуванням змінних: змінну в межах одного звичайного контексту не можна повторно призначити іншому значенню. Обчислення будуються з виразів, а рішення часто приймаються за допомогою зіставлення зі взірцем замість послідовної зміни стану.[47][48]
Назви змінних починаються з великої літери або підкреслення, наприклад Result чи _Unused. Назви атомів зазвичай починаються з малої літери (ok, error), а атоми зі спеціальними символами записуються в одинарних лапках ('Some name'). Крапка завершує визначення функції або іншу завершену форму, а крапка з комою розділяє альтернативні частини однієї функції.[48]
%% Обчислення факторіала зі зіставленням зі взірцем.
factorial(0) -> 1;
factorial(N) when is_integer(N), N > 0 ->
N * factorial(N - 1).
У прикладі функція визначена двома частинами: випадок для нуля та випадок для додатного цілого числа. Умова when — це охорона (guard), що обмежує допустимі значення. Якщо жодна частина функції не підходить, виникає виняток.[48]
Значення Erlang мають типи, однак тип змінної визначається під час виконання. Стандартна система не вимагає оголошувати тип кожного виразу. Водночас розробник може описувати очікувані типи через атрибути -type, -opaque та -spec, а інструмент Dialyzer аналізує можливі розбіжності й недосяжні варіанти викликів. Такий аналіз не перетворює Erlang на традиційну статично типізовану мову.[49]
У нових випусках система опису типів розвивалася: зокрема, з'явилися тип dynamic() для інструментів аналізу та підтримка nominal types. Слід розрізняти синтаксис специфікацій типів, можливості аналізатора та перевірки, які справді здійснюються під час виконання.[35][37]
До основних типів Erlang належать цілі числа довільної точності, числа з рухомою комою, атоми, кортежі, списки, бінарні дані, карти (maps), а також ідентифікатори процесів, посилання, порти й функціональні об'єкти. Логічні значення true і false представлені атомами, але використовуються як булеві значення в логічних операціях.[47]
Атом — іменоване незмінне символьне значення, наприклад ok, timeout або 'DOWN'. На відміну від рядка, атом зазвичай використовують для позначення стану, команди чи ключової категорії. Створювати атоми з довільного неперевіреного введення небезпечно, оскільки їхня кількість у віртуальній машині обмежена.[47]
Ідентифікатор процесу (pid) вказує на процес Erlang, посилання (reference) застосовують як унікальні маркери запитів чи подій, а порт (port) представляє канал взаємодії із зовнішніми програмами або драйверами.[47][42]
Список — рекурсивна послідовність із голови та хвоста; її можна розкласти зіставленням [Head | Tail]. Кортеж — структура з визначеною кількістю елементів, записаних у фігурних дужках, наприклад {ok, 42}. Обидва типи можуть містити різнорідні терми. Змінна не може послідовно отримувати інші значення, тому нові версії структур створюються як нові значення.[47]
First = [10, 20, 30],
[Head | Tail] = First, % Head = 10, Tail = [20,30]
Response = {ok, Head}.
Історично рядки в Erlang представляли списками цілих чисел — кодових точок символів; сучасні програми також широко використовують бінарні рядки UTF-8. У коді потрібно враховувати відмінність між списком символів, двійковою послідовністю байтів та їхніми способами кодування. Запис "abc" традиційно створює список кодових точок, а <<"abc">> — бінарну послідовність байтів.[47]
Бінарні дані записують між << та >>. Синтаксис дозволяє задавати розмір полів, знаковість та кодування, тому придатний для роботи з мережевими протоколами та файловими форматами. Bitstrings можуть мати довжину, не кратну восьми бітам, тоді як звичайний binary складається з цілої кількості байтів.[50]
Packet = <<5:8, 1024:16/big-unsigned-integer>>,
<<Version:8, Length:16/big-unsigned-integer>> = Packet.
Вирази для зіставлення з взірцем використовують під час виклику функцій, у конструкціях case і receive, а також для розбору кортежів, списків, карт і бінарних даних. Якщо взірець не підходить, відповідна гілка не вибирається; у звичайному операторі зіставлення невідповідність породжує виняток.[48]
Карти (maps) — асоціативні структури, що зіставляють ключі зі значеннями. Вони з'явилися у випуску OTP 17, а пізніше мова отримала додаткові засоби роботи з ними, включно з генераторами. Приклад створення та оновлення карти:[24][35]
Person = #{name => <<"Olena">>, age => 30},
Older = Person#{age := 31},
#{age := Age} = Older.
Записи (records) — традиційний засіб оголошувати іменовані поля, який компілятор реалізує переважно через кортежі. Поля оголошують директивою -record, а доступ до них позначають символом #. Із OTP 29 експериментально запроваджено native records, які мають окрему реалізацію та інші властивості порівняно зі звичайними записами.[38][47]
Мова підтримує арифметичні, побітові, логічні оператори та оператори порівняння. Для перевірки структурної рівності застосовують ==, а для точної рівності без автоматичного прирівнювання чисел різних видів — =:=; оператори /= та =/= означають нерівність. Порядок термів у порівняннях визначений правилами мови й не тотожний лексикографічному порядку текстових представлень.[48]
Функції в Erlang визначаються ім'ям та кількістю аргументів (arity): send/2 і send/3 — різні функції. Підтримуються рекурсія, функції вищого порядку й анонімні функції fun. Важливим способом ефективного повторення обчислень є хвостова рекурсія; для прикладного коду вона часто замінює цикли, властиві імперативним мовам.[48]
sum(List) -> sum(List, 0).
sum([], Acc) -> Acc;
sum([X | Rest], Acc) -> sum(Rest, Acc + X).
Умовний вибір реалізують через case, if і частини функцій з охоронами; для обробки винятків існує try. Включення списків утворюють нові колекції з результатів перебору, а конструкція maybe дозволяє послідовно перевіряти умовні зіставлення без багаторівневого вкладення case. У сучасних версіях існують також генератори карт, строгі генератори та zip-генератори.[48][37]
Програма зазвичай складається з модулів у файлах .erl. Атрибут -module задає назву модуля, -export визначає видимі з інших модулів функції, а -spec описує їхні типи. Після компіляції за допомогою erlc чи модуля compile створюється файл .beam, що завантажується в ERTS і виконується BEAM.[3]
-module(greeting).
-export([hello/1]).
-spec hello(string()) -> string().
hello(Name) ->
"Привіт, " ++ Name ++ "!".
Дистрибутив Erlang/OTP включає компілятор, систему виконання ERTS й прикладні бібліотеки. Під час розвитку платформи використовувалися різні проміжні представлення коду, зокрема Core Erlang та SSA; з OTP 24 спеціалізований JIT-компілятор BeamAsm створює машинні інструкції для підтримуваних архітектур під час завантаження BEAM-коду.[9][32]

Код Erlang можна виконувати кількома способами. У звичайних програмах модулі спочатку компілюють у байткод BEAM. До Erlang/OTP 24 його зазвичай виконував інтерпретатор інструкцій віртуальної машини; у сучасних збірках для x86-64 та AArch64 JIT-компілятор BeamAsm перетворює ці інструкції на машинний код під час завантаження модуля. В обох випадках виконується вже скомпільований код.[9][51]
Erlang також уміє інтерпретувати окремі вирази без створення байткоду для них. Для цього в стандартній бібліотеці є модуль erl_eval. Він обчислює вирази за їхнім абстрактним синтаксичним деревом, яке створює аналізатор erl_parse. Наприклад, інтерактивна оболонка може обчислити введений вираз 1 + 2., не створюючи окремого .beam-файлу. Сам erl_eval написаний мовою Erlang і працює всередині ERTS; якщо з оболонки викликати функцію вже скомпільованого модуля, вона виконається через BEAM.[52][53]
Ще одне значення слова «інтерпретація» використовується у налагоджувачі Erlang: він дозволяє виконувати вибрані модулі покроково та встановлювати точки зупину. Для цього потрібен скомпільований модуль із налагоджувальною інформацією, тому такий режим не тотожний виконанню довільного вихідного файлу без компіляції. Інтерпретацію виразів і механізми виконання байткоду доцільно розглядати окремо.[54]
Препроцесор epp підтримує приєднання заголовкових файлів .hrl через -include або -include_lib, текстові макроси -define та умовні директиви -ifdef, -ifndef й -endif. На відміну від функцій, макроси розгортаються до компіляції.[55]
-define(DEFAULT_TIMEOUT, 5000).
wait_for_message() ->
receive
Msg -> {ok, Msg}
after ?DEFAULT_TIMEOUT ->
timeout
end.
Функція spawn(Fun) створює новий процес, який виконує анонімну функцію без аргументів. Кожний процес має власну поштову скриньку, а receive забезпечує вибіркове отримання повідомлень. Повідомлення, що не підходять до наявних взірців, залишаються в скриньці для подальшої обробки. Для обмеження очікування існує частина after.[42]
Parent = self(),
Pid = spawn(fun() ->
receive
{ping, From} -> From ! pong
end
end),
Pid ! {ping, Parent},
receive
pong -> ok
end.
Вибіркове отримання дозволяє реалізовувати прикладні протоколи, але надмірне накопичення повідомлень збільшує витрати пам'яті та може ускладнювати пошук потрібного повідомлення. Тому робочі процеси слід проєктувати з урахуванням обмеження навантаження та часу очікування. У OTP 28 додано механізм пріоритетних повідомлень для спеціальних сценаріїв, проте він не замінює загального керування навантаженням.[42][37]
Операція link(Pid) установлює двосторонній зв'язок завершення, тоді як erlang:monitor(process, Pid) дозволяє спостерігати за процесом без спільної долі завершення. Якщо процес отримує сигнал завершення від зв'язаної сутності, його реакцію можна змінювати, зокрема налаштуванням process_flag(trap_exit, true). У прикладних системах ці низькорівневі механізми зазвичай використовуються всередині стандартних поведінок OTP.[42][5]
Звичайне введення-виведення забезпечують модулі io, file та інші частини стандартної бібліотеки. Для роботи з мережами використовують, зокрема, gen_tcp, gen_udp і ssl. Порти призначені для взаємодії з зовнішніми виконуваними програмами й драйверами. Команди введення-виведення можуть виконуватися асинхронно щодо інших процесів Erlang завдяки організації середовища виконання.[4][42]
Open Telecom Platform (OTP) — сукупність бібліотек, стандартних програмних абстракцій та правил проєктування, які застосовують разом із мовою Erlang. Попри історичну назву, OTP використовують не тільки в телекомунікаційних застосунках. Її компоненти охоплюють життєвий цикл застосунків, мережеві протоколи, криптографію, сховища даних, журналювання, тестування й інструменти діагностики.[56]
Основними складовими платформи є ERTS (середовище виконання, включно з BEAM), kernel і stdlib (базові служби та бібліотеки), sasl (підтримка експлуатації й звітності), crypto й ssl (криптографічні функції й захищені з'єднання), а також численні додаткові застосунки. Версія Erlang/OTP описує набір компонентів, які розробники платформи тестували разом.[12]
Поведінки (behaviours) — стандартні шаблони побудови процесів із визначеними зворотними викликами. Наприклад, gen_server організовує процес із внутрішнім станом та обробкою синхронних викликів, асинхронних повідомлень й інших подій; gen_statem — процес як скінченний автомат. Поведінки не замінюють бізнес-логіку, а надають узгоджений спосіб реалізації її життєвого циклу.[56][57]
Супервізор (supervisor) керує запуском, зупиненням та перезапуском дочірніх процесів за визначеною стратегією. Супервізори можуть утворювати ієрархію — дерево нагляду. За різних стратегій збій одного процесу спричиняє перезапуск тільки його самого або групи взаємозалежних процесів. Слід обирати межі відновлення так, щоб перезапуски не приховували систематичних помилок і не призводили до неконтрольованих циклів.[5]
ETS (Erlang Term Storage) — таблиці термів у пам'яті, до яких можуть звертатися кілька процесів одного вузла. ETS корисна для кешів, лічильників і тимчасових даних, але зазвичай не замінює зовнішню систему довготривалого зберігання. DETS зберігає таблиці термів у файлах; Mnesia — система керування даними зі схемою таблиць, транзакціями та засобами розподіленого зберігання. Вибір між ними залежить від вимог до надійності, продуктивності й узгодженості даних.[44][58][59]
Термін реліз в OTP може означати не лише випуск самої платформи, а й комплект застосунків, зібраний для запуску окремого програмного продукту. Інструменти OTP визначають склад такої системи, порядок запуску, конфігурацію та оновлення компонентів. Сценарії оновлення можуть використовувати гарячу заміну коду, але складні зміни внутрішнього стану або схеми даних потребують окремої міграції.[46][56]
Інтерактивна оболонка erl дозволяє вводити та одразу обчислювати вирази, компілювати модулі й взаємодіяти з процесами запущеного вузла. Як описано вище, окремі вирази вона обчислює через erl_eval, без створення для них BEAM-файлів. Модуль debugger та системні засоби трасування допомагають знаходити помилки. У сучасних випусках оболонка має автодоповнення та засоби роботи із записами, картами й специфікаціями типів.[35][52][53]
Програма Observer дає графічне уявлення про процеси, використання пам'яті й параметри вузла. Трасування подій дає змогу аналізувати виклики функцій та обмін повідомленнями, однак детальне спостереження за високонавантаженою системою саме по собі може створювати додаткове навантаження.[22]
Erlang/OTP містить засоби генерації документації, зокрема edoc, а сучасні випуски підтримують нові способи додавати документацію безпосередньо до модулів. Інструмент Dialyzer виконує статичний аналіз за принципом поступового виявлення підозрілих типових невідповідностей. Common Test забезпечує сценарії інтеграційного та системного тестування, а EUnit — модульні тести. Для профілювання використовують інструменти eprof, fprof та інші компоненти ERTS.[49][36][22]
Крім основної документації, розвиток Erlang обговорюють через Erlang Enhancement Proposals (EEP) — пропозиції змін мови й платформи. Вони документують обговорювані рішення, проте сама наявність EEP не означає, що відповідну можливість уже реалізовано у стабільному випуску.[60]
Erlang може взаємодіяти із зовнішніми програмами через порти та мережеві протоколи. Інший спосіб — NIF (Native Implemented Function): функція, реалізована переважно мовою C, може викликатися як Erlang-функція. Проте некоректний нативний код здатний порушити ізоляцію процесів або призвести до аварійного завершення всієї віртуальної машини. Тривалі нативні виклики потрібно організовувати з огляду на планування роботи процесів, зокрема використовуючи dirty schedulers там, де це доцільно.[61]
Для інтеграції з Java існує бібліотека jinterface; із мовою C — бібліотеки та формати обміну Erlang-термами. На віртуальній машині BEAM працюють і деякі інші мови, зокрема Elixir, які можуть викликати бібліотеки Erlang і використовувати значну частину екосистеми OTP.[4]
Erlang створювали для обладнання та серверних служб телекомунікацій, де необхідно обробляти багато незалежних запитів і відновлювати окремі частини системи без повної зупинки. Історично технологію використовували в Ericsson, а згодом її застосування розширилося на різні види мережевих служб. Для таких систем особливо важливі ізоляція процесів, диспетчеризація повідомлень і механізми нагляду OTP.[7][6]
Erlang використовують у програмному забезпеченні з великою кількістю одночасних з'єднань. Серед відомих прикладів — RabbitMQ, брокер повідомлень із реалізацією на Erlang, та Apache CouchDB, документоорієнтована система керування базами даних. Ці продукти демонструють застосування BEAM і OTP поза телекомунікаційною галуззю; водночас конкретні властивості масштабованості й доступності залежать від їхніх власних архітектур та налаштувань.[62][63]
Ізоляція процесів, асинхронні повідомлення, нагляд за збоями та розподілене виконання роблять Erlang зручною для певного класу триваложивучих серверних систем. Завдяки функційним засобам можна явно описувати перетворення даних і керувати окремим станом процесів без загальної змінюваної пам'яті на рівні прикладного коду.[1][6]
Серед обмежень — необхідність уважно проєктувати протоколи повідомлень, контролювати довжину поштових скриньок та враховувати особливості збирання сміття, динамічної типізації й мережевих відмов. Не всі обчислення виграють від великої кількості ізольованих процесів: частина чисельних задач або тісно пов'язаних обчислень може потребувати спеціалізованих бібліотек чи нативного коду. Дослідження масштабованості Erlang вказують також на компроміси у великих розподілених системах та на витрати підтримання спільного стану.[11][43][61]
Після відкриття вихідного коду поширення Erlang підтримували конференції, дослідницькі проєкти, відкриті бібліотеки й інструменти. Ідеї Erlang — ізольовані процеси, обмін повідомленнями та ієрархічне відновлення — вплинули на реалізації конкурентності в інших мовах і фреймворках. Зокрема, Elixir працює на BEAM та використовує бібліотеки Erlang/OTP, тоді як Akka запозичує окремі ідеї акторної моделі в середовищі JVM. Підхід до обміну повідомленнями не означає повної технічної сумісності між цими системами.[4][11]
- 1 2 3 4 About Erlang/OTP. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 Academic and Historical Questions. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 Compilation and Code Loading. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 Erlang/OTP. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 Supervisor Behaviour. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 5 6 Armstrong, Joe (2003). Background. Making Reliable Distributed Systems in the Presence of Software Errors (PDF) (англ.). Royal Institute of Technology.
- 1 2 3 4 Armstrong, Joe (2007). A History of Erlang. Proceedings of the Third ACM SIGPLAN Conference on History of Programming Languages (англ.). ACM: 6-1 — 6-26. doi:10.1145/1238844.1238850.
- ↑ Bjarne Däcker (1 лютого 1999). Erlang, the mathematician?. Erlang Questions mailing list (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 5 6 7 8 9 10 11 Björn Gustavsson (18 червня 2018). A Brief History of the BEAM Compiler. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ Downloads. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 5 Trinder, Phil; Chechina, Natalia; Papaspyrou, Nikolaos; Sagonas, Konstantinos; Thompson, Simon (17 серпня 2017). Scaling Reliably: Improving the Scalability of the Erlang Distributed Actor Platform. ACM Transactions on Programming Languages and Systems (англ.). 39 (4): 17:1–17:46. doi:10.1145/3107937. Процитовано 20 жовтня 2026.
- 1 2 3 Versions. Erlang System Documentation (англ.). Erlang/OTP. Процитовано 20 жовтня 2026.
- 1 2 Highlights: Erlang 5.0/OTP R7B. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ Highlights: Erlang 5.1/OTP R8B. Erlang/OTP Documentation (архівний примірник, Trinity College Dublin) (англ.). Процитовано 20 жовтня 2026.
- 1 2 Björn Gustavsson (1 грудня 2020). The Road to the JIT. Erlang/OTP (англ.). Процитовано 21 жовтня 2026.
- ↑ Highlights in Erlang 5.2/OTP R9B (PDF). Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ genop.tab — інструкції BEAM та примітки щодо їхніх версій. Erlang/OTP source code (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 Highlights: Erlang 5.5/OTP R11B. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ Highlights: Erlang 5.6/OTP R12B. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ Raimo Niskanen (25 листопада 2009). R13B03 has been released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ Erlang/OTP R14B Release Notes. Erlang/OTP (англ.). 15 вересня 2010. Процитовано 20 жовтня 2026.
- 1 2 3 Kenneth Lundin (14 грудня 2011). R15B a new major release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ Kenneth Lundin (27 лютого 2013). OTP R16B has been released. Erlang Questions mailing list (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 Kenneth Lundin (9 квітня 2014). Erlang OTP 17.0 has been released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 Henrik Nord (24 червня 2015). Erlang/OTP 18.0 has been released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 Henrik Nord (22 червня 2016). Erlang/OTP 19.0 has been released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 Kenneth Lundin (21 червня 2017). Erlang/OTP 20.0 is released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 Henrik Nord (20 червня 2018). Erlang OTP 21.0 is released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ Henrik Nord (14 травня 2019). Erlang OTP 22.0 is released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ Kenneth Lundin (13 травня 2020). OTP 23 Highlights. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ Erlang/OTP 23.0. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 Henrik Nord (12 травня 2021). OTP 24.0 Release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ BeamAsm, the Erlang JIT. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 Henrik Nord (18 травня 2022). Erlang/OTP 25.0 Release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 5 Henrik Nord (16 травня 2023). Erlang/OTP 26.0 Release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 Björn Gustavsson (15 травня 2024). Erlang/OTP 27.0 Release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 5 Henrik Nord (21 травня 2025). Erlang/OTP 28.0. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 Henrik Nord (13 травня 2026). Erlang/OTP 29.0. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- ↑ Erlang/OTP 29.1.2. Erlang/OTP (англ.). 14 жовтня 2026. Процитовано 20 жовтня 2026.
- ↑ Erlang/OTP 23. Erlang/OTP (англ.). Процитовано 21 жовтня 2026.
- ↑ Erlang/OTP 29. Erlang/OTP (англ.). Процитовано 21 жовтня 2026.
- 1 2 3 4 5 6 7 8 9 10 Processes. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 Efficiency Guide: Processes. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 ets. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ Distributed Erlang. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 Releases. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 5 6 7 Data Types. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 4 5 6 7 Expressions. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 dialyzer. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ Bit Syntax. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ BeamAsm, the Erlang JIT. Erlang/OTP Documentation (англ.). Процитовано 21 жовтня 2026.
- 1 2 erl_eval. Erlang/OTP Documentation (англ.). Процитовано 21 жовтня 2026.
- 1 2 shell. Erlang/OTP Documentation (англ.). Процитовано 21 жовтня 2026.
- ↑ Debugger. Erlang/OTP Documentation (англ.). Процитовано 21 жовтня 2026.
- ↑ Macros. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- 1 2 3 Design Principles. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ gen_server. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ dets. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ mnesia. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ Erlang Enhancement Proposals. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
- 1 2 Erlang NIFs. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
- ↑ RabbitMQ Documentation. RabbitMQ (англ.). Процитовано 20 жовтня 2026.
- ↑ Technical Overview. Apache CouchDB (англ.). Процитовано 20 жовтня 2026.
- Armstrong, Joe. Making Reliable Distributed Systems in the Presence of Software Errors. Stockholm: Royal Institute of Technology, 2003. Повний текст.
- Armstrong, Joe. A History of Erlang // Proceedings of the Third ACM SIGPLAN Conference on History of Programming Languages. ACM, 2007. DOI: 10.1145/1238844.1238850.
- Cesarini, Francesco; Thompson, Simon. Erlang Programming. O'Reilly Media, 2009. ISBN 978-0-596-51818-9.
- Logan, Martin; Merritt, Eric; Carlsson, Richard. Erlang and OTP in Action. Manning, 2011. ISBN 978-1-933988-78-8.
- Hébert, Fred. Learn You Some Erlang for Great Good!. No Starch Press, 2013. ISBN 978-1-59327-435-1.