Перейти до вмісту

Erlang

Очікує на перевірку
Матеріал з Вікіпедії — вільної енциклопедії.
Erlang
Парадигмафункційна, конкурентна, розподілена
Дата появи1986
ТворціДжо Армстронг, Роберт Вірдінг, Майк Вільямс
РозробникEricsson, спільнота розробників
Останній реліз29.1.2 (14 жовтня, 2026; 27 днів тому (2026-10-14))
Система типізаціїдинамічна, сильна
Під впливом відProlog, Smalltalk, Lisp, PLEX
Вплинула наElixir, Akka
Мова реалізаціїC Редагувати інформацію у Вікіданих
Операційна системабагатоплатформова
ЛіцензіяApache License 2.0
Звичайні розширення файлів.erl, .hrl, .beam
Репозиторій вихідного кодуgithub.com/erlang/otp Редагувати інформацію у Вікіданих
Вебсайтwww.erlang.org

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]

Роберт Вірдінг і Джо Армстронг, 2013 рік

Назва 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/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 ізольовані, але формулювання «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 можна виконувати кількома способами. У звичайних програмах модулі спочатку компілюють у байткод 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]

Екосистема Erlang/OTP

[ред. | ред. код]

Бібліотеки та компоненти

[ред. | ред. код]

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, DETS та Mnesia

[ред. | ред. код]

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. 1 2 3 4 About Erlang/OTP. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  2. 1 2 Academic and Historical Questions. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  3. 1 2 3 Compilation and Code Loading. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  4. 1 2 3 4 Erlang/OTP. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  5. 1 2 3 4 Supervisor Behaviour. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  6. 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.
  7. 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.
  8. ↑ Bjarne Däcker (1 лютого 1999). Erlang, the mathematician?. Erlang Questions mailing list (англ.). Процитовано 20 жовтня 2026.
  9. 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.
  10. ↑ Downloads. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  11. 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.
  12. 1 2 3 Versions. Erlang System Documentation (англ.). Erlang/OTP. Процитовано 20 жовтня 2026.
  13. 1 2 Highlights: Erlang 5.0/OTP R7B. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  14. ↑ Highlights: Erlang 5.1/OTP R8B. Erlang/OTP Documentation (архівний примірник, Trinity College Dublin) (англ.). Процитовано 20 жовтня 2026.
  15. 1 2 Björn Gustavsson (1 грудня 2020). The Road to the JIT. Erlang/OTP (англ.). Процитовано 21 жовтня 2026.
  16. ↑ Highlights in Erlang 5.2/OTP R9B (PDF). Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  17. ↑ genop.tab — інструкції BEAM та примітки щодо їхніх версій. Erlang/OTP source code (англ.). Процитовано 20 жовтня 2026.
  18. 1 2 3 4 Highlights: Erlang 5.5/OTP R11B. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
  19. ↑ Highlights: Erlang 5.6/OTP R12B. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
  20. ↑ Raimo Niskanen (25 листопада 2009). R13B03 has been released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  21. ↑ Erlang/OTP R14B Release Notes. Erlang/OTP (англ.). 15 вересня 2010. Процитовано 20 жовтня 2026.
  22. 1 2 3 Kenneth Lundin (14 грудня 2011). R15B a new major release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  23. ↑ Kenneth Lundin (27 лютого 2013). OTP R16B has been released. Erlang Questions mailing list (англ.). Процитовано 20 жовтня 2026.
  24. 1 2 3 Kenneth Lundin (9 квітня 2014). Erlang OTP 17.0 has been released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  25. 1 2 Henrik Nord (24 червня 2015). Erlang/OTP 18.0 has been released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  26. 1 2 Henrik Nord (22 червня 2016). Erlang/OTP 19.0 has been released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  27. 1 2 Kenneth Lundin (21 червня 2017). Erlang/OTP 20.0 is released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  28. 1 2 Henrik Nord (20 червня 2018). Erlang OTP 21.0 is released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  29. ↑ Henrik Nord (14 травня 2019). Erlang OTP 22.0 is released. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  30. ↑ Kenneth Lundin (13 травня 2020). OTP 23 Highlights. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  31. ↑ Erlang/OTP 23.0. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  32. 1 2 Henrik Nord (12 травня 2021). OTP 24.0 Release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  33. ↑ BeamAsm, the Erlang JIT. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
  34. 1 2 Henrik Nord (18 травня 2022). Erlang/OTP 25.0 Release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  35. 1 2 3 4 5 Henrik Nord (16 травня 2023). Erlang/OTP 26.0 Release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  36. 1 2 3 4 Björn Gustavsson (15 травня 2024). Erlang/OTP 27.0 Release. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  37. 1 2 3 4 5 Henrik Nord (21 травня 2025). Erlang/OTP 28.0. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  38. 1 2 3 Henrik Nord (13 травня 2026). Erlang/OTP 29.0. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  39. ↑ Erlang/OTP 29.1.2. Erlang/OTP (англ.). 14 жовтня 2026. Процитовано 20 жовтня 2026.
  40. ↑ Erlang/OTP 23. Erlang/OTP (англ.). Процитовано 21 жовтня 2026.
  41. ↑ Erlang/OTP 29. Erlang/OTP (англ.). Процитовано 21 жовтня 2026.
  42. 1 2 3 4 5 6 7 8 9 10 Processes. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  43. 1 2 Efficiency Guide: Processes. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  44. 1 2 ets. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
  45. ↑ Distributed Erlang. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  46. 1 2 Releases. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  47. 1 2 3 4 5 6 7 Data Types. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  48. 1 2 3 4 5 6 7 Expressions. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  49. 1 2 dialyzer. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
  50. ↑ Bit Syntax. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  51. ↑ BeamAsm, the Erlang JIT. Erlang/OTP Documentation (англ.). Процитовано 21 жовтня 2026.
  52. 1 2 erl_eval. Erlang/OTP Documentation (англ.). Процитовано 21 жовтня 2026.
  53. 1 2 shell. Erlang/OTP Documentation (англ.). Процитовано 21 жовтня 2026.
  54. ↑ Debugger. Erlang/OTP Documentation (англ.). Процитовано 21 жовтня 2026.
  55. ↑ Macros. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  56. 1 2 3 Design Principles. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  57. ↑ gen_server. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
  58. ↑ dets. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
  59. ↑ mnesia. Erlang/OTP Documentation (англ.). Процитовано 20 жовтня 2026.
  60. ↑ Erlang Enhancement Proposals. Erlang/OTP (англ.). Процитовано 20 жовтня 2026.
  61. 1 2 Erlang NIFs. Erlang System Documentation (англ.). Процитовано 20 жовтня 2026.
  62. ↑ RabbitMQ Documentation. RabbitMQ (англ.). Процитовано 20 жовтня 2026.
  63. ↑ 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.

Посилання

[ред. | ред. код]