Paradigms | Multi-paradigm : concurrent, функциональный |
---|---|
Разработан |
|
Разработчик | Ericsson |
Впервые появился | 1986; 34 года назад (1986) |
Стабильный выпуск | 23.1.1 / 2 октября 2020 г.; 19 дней назад (2020-10-02) |
Дисциплина ввода | Динамический, сильный |
Лицензия | Лицензия Apache 2.0 |
Расширения имен файлов | .erl,.hrl |
Веб-сайт | www.erlang.org |
Основные реализации | |
Erlang | |
Под влиянием | |
Lisp, PLEX, Prolog, Smalltalk | |
Под влиянием | |
Akka, Clojure, Dart, Elixir, F#, Opa, Oz, Reia, Rust, Scala | |
|
Erlang () - это универсальный, параллельный, функциональный язык программирования и со сборкой мусора исполняющая система. Термин Erlang используется взаимозаменяемо с Erlang / OTP или Open Telecom Platform (OTP), которая состоит из системы времени выполнения Erlang , в основном нескольких готовых к использованию компонентов (OTP). написана на Erlang, и набор принципов проектирования для программ на Erlang.
Система времени выполнения Erlang разработана для систем со следующими характеристиками:
Язык программирования Erlang имеет неизменяемые данные, сопоставление с образцом и функциональное программирование. Последовательное подмножество языка Erlang поддерживает активную оценку, одиночное присвоение и динамическую типизацию.
Изначально это было проприетарное программное обеспечение в Ericsson, разработанный Джо Армстронг, Робертом Вирдингом и Майком Уильямсом в 1986 году, но был выпущен как бесплатное программное обеспечение с открытым исходным кодом в 1998 году. Erlang / OTP поддерживается и обслуживается отделом продуктов Open Telecom Platform (OTP) по адресу Ericsson.
Имя Erlang, приписываемое Бьярне Декеру, было предположено теми, кто работает на теле фальшивые переключатели (для которых был разработан язык), чтобы быть ссылкой на датского математика и инженера Агнера Крарупа Эрланга и слоговое сокращение от "Ericsson Language". Erlang был разработан с целью улучшения разработки приложений телефонии. Первоначальная версия Erlang была реализована в Prolog и на нее повлиял язык программирования PLEX, который использовался на более ранних биржах Ericsson. К 1988 году Erlang доказал, что он подходит для прототипирования телефонных станций, но интерпретатор Prolog был слишком медленным. Одна группа в компании Ericsson подсчитала, что для использования в производстве потребуется в 40 раз быстрее. В 1992 году началась работа над виртуальной машиной (VM) BEAM, которая компилирует Erlang в C, используя смесь встроенного кода и многопоточного кода для достижения баланса между производительностью и дисковым пространством. По словам Армстронга, язык перешел от лабораторного продукта к реальным приложениям после краха телефонной станции следующего поколения AX под названием AX-N в 1995 году. В результате был выбран Erlang. для следующего режима асинхронной передачи (ATM), обмен AXD.
В 1998 году Эрикссон анонсировал коммутатор AXD301, содержащий более миллиона строк Erlang, и сообщил о достижении высокой доступности из девяти "9" сек. Вскоре после этого Ericsson Radio Systems запретила внутреннее использование Erlang для новых продуктов, сославшись на предпочтение непатентованных языков. Запрет заставил Армстронга и других покинуть Ericsson. В конце года исходный код реализации был открыт. В конце концов Эрикссон снял запрет и повторно нанял Армстронга в 2004 году.
В 2006 году встроенная поддержка симметричной многопроцессорной обработки была добавлена в исполняющую систему и виртуальную машину.
Джо Армстронг, соавтор Erlang, суммировал принципы процессов в своей PhD диссертации :
Джо Армстронг заметил в интервью Rackspace в 2013 году: «Если Java - это« написать один раз, запустить где угодно », то Erlang - это« написать один раз, работать вечно ».
В 2014 г. Ericsson сообщила, что Erlang используется в своих узлах поддержки и в мобильных сетях GPRS, 3G и LTE по всему миру, а также в Nortel и T-Mobile.
As Тим Брэй, директор по веб-технологиям в Sun Microsystems, в своем программном выступлении на O'Reilly Open Source Convention (OSCON) в июле 2008 года выразился:
Если бы кто-нибудь пришел мне и хотел заплатить мне много денег, чтобы построить крупномасштабную систему обработки сообщений, которая действительно должна была работать все время, никогда не могла позволить себе падать годами, я бы без колебаний выбрал Erlang, чтобы встроить ее.
Erlang - это язык программирования, используемый для кодирования WhatsApp.
С момента выхода в виде открытого исходного кода Erlang распространился за пределы телекоммуникаций, утвердившись в других вертикалях, таких как FinTech, игры, здравоохранение, автомобилестроение, Интернет вещей и Блокчейн. Помимо WhatsApp, среди историй успеха Erlang указаны и другие компании: Vocalink (компания MasterCard), Goldman Sachs, Nintendo, AdRoll, Grindr, BT Mobile, Samsung, OpenX, SITA.
A factorial реализованный на Erlang алгоритм:
-модуль (факт). % Это файл "fact.erl", модуль и имя файла должны соответствовать -export ([fac / 1]). % Экспорт функции 'fac' арности 1 (1 параметр, без типа, без имени) fac (0) ->1; % Если 0, то верните 1, в противном случае (обратите внимание на точку с запятой; означает «иначе») fac (N), когда N>0, is_integer (N) ->N * fac (N-1). % Рекурсивно определить, а затем вернуть результат% (обратите внимание на точку., Означающую «endif» или «конец функции») %% Эта функция выйдет из строя, если будет задано что-либо, кроме неотрицательного целого числа. %% Это иллюстрирует философию Erlang «Пусть он рухнет».
Конечный рекурсивный алгоритм, который создает последовательность Фибоначчи :
%% Объявление модуля должно соответствовать имени файла "series.erl" -module (series). %% Оператор экспорта содержит список всех тех функций, которые составляют %% общедоступный API модуля. В этом случае этот модуль предоставляет единственную функцию %% с именем fib, которая принимает 1 аргумент (IE имеет арность 1) %% Общий синтаксис для -export - это список, содержащий имя и %% арность каждой публичной функции -export ([fib / 1]). %% ------------------------------------------------ --------------------- %% Общедоступный API %% ----------------------- ---------------------------------------------- %% Обработка случаев в котором fib / 1 получает определенные значения %% Порядок, в котором объявляются эти сигнатуры функций, является важной %% частью функциональности этого модуля %% Если fib / 1 передается точно целое число 0, тогда возвращается 0 fib (0) ->0; %% Если fib / 1 получает отрицательное число, возвращается атом err_neg_val %% Обычно такое защитное кодирование не приветствуется из-за философии Erlang «Let %% it Crash»; однако в этом случае мы должны явно %% предотвратить ситуацию, которая приведет к сбою механизма выполнения Erlang fib (N), когда N < 0 ->err_neg_val; %% Если в fib / 1 передано целое число меньше 3, то возвращается 1 %% Предыдущие две сигнатуры функций обрабатывают все случаи, когда N <1, %%, поэтому эта сигнатура функции обрабатывает случаи, когда N = 1 или N = 2 fib ( N) когда N < 3 ->1; %% Для всех остальных значений вызовите частную функцию fib_int / 3, чтобы выполнить %% вычисление fib (N) ->fib_int (N, 0, 1). %% ------------------------------------------------ --------------------- %% Частный API %% ----------------------- ---------------------------------------------- %% Если fib_int / 3 получает 1 в качестве своего первого аргумента, тогда мы закончили, поэтому %% вернет значение в аргументе B. Поскольку нас не интересует значение %% второго аргумента, мы обозначаем это с помощью _, чтобы указать% % "безразлично" значение fib_int (1, _, B) ->B; %% Для всех других комбинаций аргументов рекурсивно вызовите fib_int / 3 %%, где каждый вызов делает следующее: %% - счетчик уменьшения N %% - берет предыдущее значение фибоначчи в аргументе B и передает его как %% аргумент A %% - Вычислить значение текущего числа Фибоначчи и передать его %% в качестве аргумента B fib_int (N, A, B) ->fib_int (N-1, B, A + B).
Вот та же программа без пояснительных комментариев:
-модуль (серия). -export ([fib / 1]). fib (0) ->0; fib (N), когда N < 0 ->err_neg_val; fib (N), когда N < 3 ->1; fib (N) ->fib_int (N, 0, 1). fib_int (1, _, B) ->B; fib_int (N, A, B) ->fib_int (N-1, B, A + B).
Quicksort в Erlang, используя понимание списка :
%% qsort: qsort (List) %% Сортировать список элементов -module (qsort). % Это файл 'qsort.erl' -export ([qsort / 1]). % Экспортируется функция 'qsort' с 1 параметром (без типа, без имени) qsort () ->; % Если список пуст, вернуть пустой список (нечего сортировать) qsort ([Pivot | Rest]) ->% Составить рекурсивно список с 'Front' для всех элементов, которые должны быть перед 'Pivot'%, затем 'Pivot' затем «Назад» для всех элементов, которые должны быть после qsort «Развернуть» ([Передний || Передний <- Rest, Front < Pivot]) ++ [Pivot] ++ qsort([Back || Back <- Rest, Back>= Поворот]).
В приведенном выше примере рекурсивно вызывается функция qsort
, пока не останется ничего для сортировки. Выражение [Front || Front <- Rest, Front < Pivot]
- это понимание списка, означающее «Создайте список элементов Front
так, чтобы Front
был членом Rest
, и Передний
меньше, чем Поворот
. " ++
- оператор конкатенации списка.
Функция сравнения может использоваться для более сложных структур для удобства чтения.
Следующий код сортирует списки по длине:
% Это файл "listsort.erl" (компилятор сделан таким образом) -module (listsort). % Export 'by_length' с 1 параметром (неважно тип и имя) -export ([by_length / 1]). by_length (Lists) ->% Используйте 'qsort / 2' и предоставляет анонимную функцию в качестве параметра qsort (Lists, fun (A, B) ->length (A) < length(B) end). qsort(, _)->;% Если список пуст, вернуть пустой list (игнорировать второй параметр) qsort ([Pivot | Rest], Smaller) ->% Разделить список с элементами «Smaller» перед «Pivot» и не-«Smaller »% после« Pivot »и отсортировать подсписки. qsort ([X || X <- Rest, Smaller(X,Pivot)], Smaller) ++ [Pivot] ++ qsort([Y || Y <- Rest, not(Smaller(Y, Pivot))], Smaller).
A Pivot
берется из первого параметра, заданного в qsort ()
, а остальные Lists
имеют имя Rest
. Обратите внимание, что выражение
[X || X <- Rest, Smaller(X,Pivot)]
не отличается по форме от
[Front || Front <- Rest, Front < Pivot]
(в предыдущем примере), за исключением использования функции сравнения в последняя часть, в которой говорится: «Создайте список элементов X
так, чтобы X
был членом Rest
, а Smaller
был истинным», где Меньший
был определен ранее как
fun (A, B) ->length (A) < length(B) end
Анонимная функция названа Smaller
в список параметров второго определения qsort
, чтобы на него можно ссылаться по этому имени в этой функции. Он не упоминается в первом определении qsort
, которое имеет дело с базовым случаем пустого списка и, таким образом, не нуждается в этой функции, не говоря уже о ее имени.
Erlang имеет восемь примитивов типов данных :
make_ref()
.spawn (...)
Pid - это ссылки на процессы Erlang.open_port
. Сообщения могут отправляться и приниматься из портов, но эти сообщения должны подчиняться так называемому «протоколу порта».fun (...) ->... end
.И три составных типа данных:
{D1, D2,..., Dn}
обозначает кортеж, аргументами которого являются D1, D2,... Dn.
Аргументы могут быть примитивными типами данных или составными данными типы. К любому элементу кортежа можно получить доступ за постоянное время.[Dh | Dt]
обозначает список, первым элементом которого является Dh
, а оставшимися элементами является список Dt
. Синтаксис обозначает пустой список. Синтаксис [D1, D2,.., Dn]
является сокращением от [D1 | [D2 |.. | [Dn | ]]]
. К первому элементу списка можно получить доступ в постоянное время. Первый элемент списка называется заголовком списка. Остаток списка после удаления его заголовка называется хвостом списка.
# {Key1 =>Value1,..., KeyN =>ValueN}
.Предусмотрены две формы синтаксического сахара :
[99,97,116pting
.В Erlang нет метода для определения классов, хотя есть внешние библиотеки доступны.
В большинстве других языков программирования сбои программного обеспечения всегда считались (и часто до сих пор считаются) крайне нежелательными ситуациями, которых следует избегать любой ценой. Следовательно, существуют сложные механизмы обработки исключений, позволяющие улавливать эти ситуации и затем смягчать их последствия. Эта философия проектирования существует потому, что многие из основополагающих принципов проектирования программного обеспечения были определены в то время, когда компьютеры были однопроцессорными. В этих условиях сбои программного обеспечения действительно были фатальными. Учитывая это основное ограничение, было совершенно естественно разработать стили программирования, в которых большая часть кода была посвящена обнаружению и последующей обработке ошибочных ситуаций. Это, в свою очередь, привело непосредственно к все еще широко популярному стилю кодирования, известному как защитное программирование.
. Однако разработчики Erlang осознали, что, несмотря на их нежелательные эффекты, сбои программного обеспечения во многом похожи на смерть и налоги - они неизбежны. Поэтому вместо того, чтобы рассматривать сбой как кризисную ситуацию, которая временно приостанавливает всю нормальную работу до тех пор, пока не будет найдено решение, они рассудили, что было бы гораздо более разумным рассматривать сбой точно так же, как любое другое обычное событие времени выполнения. Следовательно, когда процесс Erlang дает сбой, эта ситуация регистрируется как просто сообщение другого типа, поступающее в почтовый ящик процесса.
Это осознание привело к тому, что дизайнеры Erlang создали язык со следующими фундаментальными особенностями:
Стиль «Пусть он сбой» Кодирование, следовательно, является практическим следствием работы на языке, который работает на этих принципах.
Типичное приложение Erlang написано в виде дерева супервизора. Эта архитектура основана на иерархии процессов, в которой процесс верхнего уровня известен как «супервизор». Затем супервизор порождает несколько дочерних процессов, которые действуют либо как рабочие, либо как супервизоры более низкого уровня. Такие иерархии могут существовать до произвольной глубины и доказали, что они обеспечивают хорошо масштабируемую и отказоустойчивую среду, в которой могут быть реализованы функциональные возможности приложения.
В дереве супервизора все процессы супервизора отвечают за управление жизненным циклом своих дочерних процессов, включая обработку ситуаций, в которых эти дочерние процессы дают сбой. Любой процесс может стать супервизором, сначала запустив дочерний процесс, а затем вызвав для этого процесса erlang: monitor / 2
. Если отслеживаемый процесс затем выйдет из строя, супервизор получит сообщение, содержащее кортеж, первым членом которого является атом 'DOWN'
. Супервизор отвечает, во-первых, за прослушивание таких сообщений, а во-вторых, за принятие соответствующих мер для исправления состояния ошибки.
Кроме того, «Let it Crash» приводит к стилю кодирования, содержащему небольшой защитный код, что приводит к уменьшению размера приложений.
Основная сила Erlang - поддержка параллелизма. Он имеет небольшой, но мощный набор примитивов для создания процессов и взаимодействия между ними. Erlang концептуально похож на язык occam, хотя он переделывает идеи взаимодействия последовательных процессов (CSP) в функциональной структуре и использует асинхронную передачу сообщений. Процессы являются основным средством структурирования приложения Erlang. Это не процессы операционной системы и потоки, а облегченные процессы, которые планируются BEAM. Подобно процессам операционной системы (но в отличие от потоков операционной системы), они не имеют общего состояния друг с другом. Предполагаемые минимальные накладные расходы для каждого составляют 300 слов. Таким образом, можно создать множество процессов без снижения производительности. В 2005 году тест производительности с 20 миллионами процессов был успешно выполнен с 64-битным Erlang на машине с 16 ГБ оперативной памяти (RAM; всего 800 байт на процесс). Erlang поддерживает симметричную многопроцессорность с момента выпуска R11B в мае 2006 года.
Хотя потокам требуется поддержка внешних библиотек на большинстве языков, Erlang предоставляет функции уровня языка для создания и управления процессы с целью упрощения параллельного программирования. Хотя в Erlang весь параллелизм является явным, процессы взаимодействуют с использованием передачи сообщений вместо общих переменных, что устраняет необходимость в явных блокировках (схема блокировки по-прежнему используется внутри виртуальной машины).
Межпроцессное взаимодействие работает через shared-nothing асинхронную систему передачи сообщений : у каждого процесса есть «почтовый ящик», очередь сообщений, отправленных другими процессами, но еще не использованных. Процесс использует примитив receive
для получения сообщений, соответствующих желаемым шаблонам. Процедура обработки сообщений по очереди проверяет сообщения на соответствие каждому шаблону, пока один из них не совпадет. Когда сообщение израсходовано и удалено из почтового ящика, процесс возобновляет выполнение. Сообщение может содержать любую структуру Erlang, включая примитивы (целые числа, числа с плавающей запятой, символы, атомы), кортежи, списки и функции.
В приведенном ниже примере кода показана встроенная поддержка распределенных процессов:
% Создайте процесс и вызовите функцию web: start_server (Port, MaxConnections) ServerProcess = spawn (web, start_server, [Port, MaxConnections]),% Создайте удаленный процесс и вызовите функцию% web: start_server (Port, MaxConnections) на машине RemoteNode RemoteProcess = spawn (RemoteNode, web, start_server, [Port, MaxConnections]),% Отправить сообщение в ServerProcess (асинхронно). Сообщение состоит из кортежа% с атомом «пауза» и числом «10». ServerProcess! {pause, 10},% Получать сообщения, отправленные этому процессу, получить a_message ->do_something; {данные, DataContent} ->дескриптор (DataContent); {привет, текст} ->io: format ("Получил приветственное сообщение: ~ s", [Текст]); {Goodbye, Text} ->io: format ("Got goodbye message: ~ s", [Text]) end.
Как показывает пример, процессы могут быть созданы на удаленных узлах, и связь с ними прозрачна в том смысле, что связь с удаленными процессами работает точно так же, как связь с локальными процессами.
Параллелизм поддерживает основной метод обработки ошибок в Erlang. Когда процесс дает сбой, он аккуратно завершается и отправляет сообщение контролирующему процессу, который затем может предпринять действия, такие как, например, запуск нового процесса, который берет на себя задачу старого процесса.
Официальная эталонная реализация Erlang использует BEAM. BEAM включен в официальный дистрибутив Erlang, который называется Erlang / OTP. BEAM выполняет байт-код , который преобразуется в многопоточный код во время загрузки. Он также включает компилятор нативного кода на большинстве платформ, разработанный в рамках проекта High Performance Erlang Project (HiPE) в Уппсальском университете. С октября 2001 года система HiPE полностью интегрирована в систему Erlang / OTP с открытым исходным кодом Ericsson. Он также поддерживает интерпретацию непосредственно из исходного кода через абстрактное синтаксическое дерево через скрипт, начиная с версии Erlang R11B-5.
Erlang поддерживает уровень языка Динамическое обновление программного обеспечения. Для реализации этого код загружается и управляется как «модульные» единицы; модуль - это единица компиляции. Система может хранить в памяти две версии модуля одновременно, и процессы могут одновременно запускать код из каждой. Версии называются «новая» и «старая». Процесс не перейдет в новую версию, пока он не сделает внешний вызов своего модуля.
Пример механизма загрузки горячего кода:
%% Процесс, единственная задача которого - вести счетчик. %% Первая версия -модуль (счетчик). -export ([начало / 0, кодовый переключатель / 1]). start () ->цикл (0). цикл (сумма) ->получение {приращение, счетчик} ->цикл (сумма + счет); {counter, Pid} ->Pid! {счетчик, сумма}, цикл (сумма); code_switch ->? MODULE: codewitch (Sum)% Принудительное использование 'codewitch / 1' с конца последней версии МОДУЛЯ. кодовый переключатель (Сумма) ->цикл (Сумма).
Для второй версии мы добавили возможность обнулить счетчик.
%% Вторая версия -модуль (счетчик). -export ([начало / 0, кодовый переключатель / 1]). start () ->цикл (0). цикл (сумма) ->получение {приращение, счетчик} ->цикл (сумма + счет); сброс ->цикл (0); {counter, Pid} ->Pid! {счетчик, сумма}, цикл (сумма); code_switch ->? МОДУЛЬ: конец кода (Sum). кодовый переключатель (Сумма) ->цикл (Сумма).
Только при получении сообщения, состоящего из атома code_switch
, цикл выполнит внешний вызов codewitch / 1 (? MODULE
- это макрос препроцессора для текущего модуля). Если в памяти есть новая версия модуля счетчика, то будет вызвана его функция codewitch / 1. Практика наличия определенной точки входа в новую версию позволяет программисту преобразовывать состояние в то, что необходимо в более новой версии. В этом примере состояние сохраняется как целое число.
На практике системы строятся с использованием принципов проектирования Open Telecom Platform, что приводит к большему количеству проектов с возможностью обновления кода. Успешная загрузка горячего кода требует больших усилий. Код должен быть написан с осторожностью, чтобы использовать возможности Erlang.
В 1998 году Ericsson выпустила Erlang как бесплатное программное обеспечение с открытым исходным кодом, чтобы обеспечить его независимость от одного поставщика и повысить осведомленность о языке. Erlang вместе с библиотеками и распределенной базой данных реального времени Mnesia формирует коллекцию библиотек OTP. Ericsson и несколько других компаний поддерживают Erlang на коммерческой основе.
С момента выпуска с открытым исходным кодом Erlang использовался несколькими фирмами по всему миру, включая Nortel и T-Mobile. Хотя Erlang был разработан, чтобы заполнить нишу и оставался малоизвестным языком на протяжении большей части своего существования, его популярность растет из-за спроса на параллельные услуги. Erlang нашел применение в развертывании серверов массовых многопользовательских ролевых онлайн-игр (MMORPG).
Викискладе есть материалы, связанные с Эрланг (язык программирования). |
В Викиучебниках есть книга на тему: Программирование на Эрланге |