Эта статья входит в число хороших статей

Erlang: различия между версиями

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
[отпатрулированная версия][отпатрулированная версия]
Содержимое удалено Содержимое добавлено
Updated erlang version.
м Сфера применения: Орфография
 
(не показаны 103 промежуточные версии 67 участников)
Строка 1: Строка 1:
{{другие значения|Эрланг (значения)}}
{{другие значения|Эрланг (значения)}}
{{Карточка языка программирования
{{Карточка языка программирования
| семантика = [[Мультипарадигмальный язык программирования|мультипарадигмальный]]: [[параллельное программирование|параллельное]], [[Функциональное программирование|функциональное]] [[программирование]]
| name = Erlang
| система типов = [[Сильная типизация|сильная]], [[Динамическая типизация|динамическая]]
| logo = Erlang logo.png
| semantics = [[Мультипарадигмальный язык программирования|мультипарадигмальный]]: [[параллельное программирование|параллельное]], [[Функциональное программирование|функциональное]] [[программирование]]
| year = 1987
| latest_release_version = 18.2.1<ref>{{cite web|url=http://www.erlang.org/news/98|title=Erlang OTP 18.2.1 has been released}}</ref>
| latest_release_date = 18 декабря 2015 года
| extension = .erl
| designer = [[Ericsson]] Computer Science Laboratory
| typing = [[Строгая типизация|строгая]], [[Динамическая типизация|динамическая]]
| implementations = Erlang, Erlang HiPE
| influenced_by = [[ML]], [[Миранда (язык программирования)|Миранда]], [[Ада (язык программирования)|Ада]], [[Модула-2]], [[CHILL]], [[Пролог (язык программирования)|Пролог]]
| dialects =
| influenced =
}}
}}
'''Erlang''' [{{IPA|ˈɜːlæŋ}}]<ref>[http://www.collinsdictionary.com/dictionary/english/erlang Definition of «erlang» — Collins English Dictionary]</ref> — [[функциональный язык программирования]] со [[строгая типизация|строгой]] [[динамическая типизация|динамической типизацией]], предназначенный для создания [[распределённые вычисления|распределённых вычислительных систем]]. Разработан и поддерживается компанией [[Ericsson]]. Язык включает в себя средства порождения параллельных [[легковесный процесс|легковесных процессов]] и их взаимодействия через [[обмен сообщениями|обмен асинхронными сообщениями]] в соответствии с [[модель акторов|моделью акторов]].


'''Erlang''' [{{IPA|ˈɜːlæŋ}}]<ref>{{Cite web |url=http://www.collinsdictionary.com/dictionary/english/erlang |title=Definition of «erlang» — Collins English Dictionary |access-date=2015-01-07 |archive-date=2015-04-08 |archive-url=https://web.archive.org/web/20150408054131/http://www.collinsdictionary.com/dictionary/english/erlang |deadlink=no }}</ref> — [[функциональный язык программирования]] с [[сильная типизация|сильной]] [[динамическая типизация|динамической типизацией]], предназначенный для создания [[распределённые вычисления|распределённых вычислительных систем]]. Разработан и поддерживается компанией [[Ericsson]]. Язык включает в себя средства порождения параллельных легковесных процессов и их взаимодействия через [[обмен сообщениями|обмен асинхронными сообщениями]] в соответствии с [[модель акторов|моделью акторов]].
Erlang был целенаправленно разработан для применения в распределённых, [[отказоустойчивая архитектура|отказоустойчивых]], параллельных [[система реального времени|системах реального времени]]{{Переход|#Мягкое реальное время}}, для которых кроме средств самого языка имеется стандартная [[библиотека (программирование)|библиотека]] модулей{{Переход|#Стандартная библиотека модулей}} и библиотека шаблонных решений (так называемых поведений) — [[Open Telecom Platform|фреймворк OTP]] ({{lang-en|Open Telecom Platform}}){{Переход|#Фреймворк OTP}}. [[Компьютерная программа|Программа]] на Erlang [[транслятор|транслируется]] в [[байт-код]], исполняемый [[виртуальная машина|виртуальными машинами]], находящимися на различных узлах распределённой{{Переход|Распределённые вычисления}} [[компьютерная сеть|вычислительной сети]]. Erlang-системы поддерживают горячую замену кода{{Переход|#Горячая замена кода}}, что позволяет эксплуатировать оборудование безостановочно.

Erlang был целенаправленно разработан для применения в распределённых, [[отказоустойчивая архитектура|отказоустойчивых]], параллельных [[система реального времени|системах реального времени]]{{Переход|#Мягкое реальное время}}, для которых, кроме средств самого языка, имеется стандартная [[библиотека (программирование)|библиотека]] модулей{{Переход|#Стандартная библиотека модулей}} и библиотека шаблонных решений (так называемых поведений) — [[Open Telecom Platform|фреймворк OTP]] ({{lang-en|Open Telecom Platform}}){{Переход|#Фреймворк OTP}}. [[Компьютерная программа|Программа]] на Erlang [[транслятор|транслируется]] в [[байт-код]], исполняемый [[виртуальная машина|виртуальными машинами]], находящимися на различных узлах [[Распределённые вычисления|распределённой]] [[компьютерная сеть|вычислительной сети]]. Erlang-системы поддерживают горячую замену кода{{Переход|#Горячая замена кода}}, что позволяет эксплуатировать оборудование безостановочно.


Свой [[синтаксис (программирование)|синтаксис]] и некоторые концепции Erlang унаследовал от языка [[логическое программирование|логического программирования]] [[Пролог (язык программирования)|Пролог]]{{sfn|Чезарини, Томпсон|2012|с=42}}. Язык поддерживает многие типы данных{{Переход|#Типы данных}}, условные конструкции{{Переход|#Условные выражения}}, [[сопоставление с образцом]]{{Переход|#Сопоставление с образцом}}, обработку исключений{{Переход|#Обработка ошибок}}, списковые включения{{Переход|#Список}} и выражения битовых строк{{Переход|#Битовые строки и бинарные данные}}, функции{{Переход|#Функции}} ([[анонимная функция|анонимные функции]]{{Переход|#Функциональный объект (Fun)}}, [[функция высшего порядка|функции высшего порядка]], [[рекурсия#В программировании|рекурсивные определения функций]], оптимизацию [[хвостовая рекурсия|хвостовой рекурсии]]), модули{{Переход|#Модули}}, приём и отправку сообщений{{Переход|#Отправка и приём сообщений}} между процессами. Препроцессор{{Переход|#Препроцессор и макросы}} поддерживает работу с макросами и включение заголовочных файлов.
Свой [[синтаксис (программирование)|синтаксис]] и некоторые концепции Erlang унаследовал от языка [[логическое программирование|логического программирования]] [[Пролог (язык программирования)|Пролог]]{{sfn|Чезарини, Томпсон|2012|с=42}}. Язык поддерживает многие типы данных{{Переход|#Типы данных}}, условные конструкции{{Переход|#Условные выражения}}, [[сопоставление с образцом]]{{Переход|#Сопоставление с образцом}}, обработку исключений{{Переход|#Обработка ошибок}}, списковые включения{{Переход|#Список}} и выражения битовых строк{{Переход|#Битовые строки и бинарные данные}}, функции{{Переход|#Функции}} ([[анонимная функция|анонимные функции]]{{Переход|#Функциональный объект (Fun)}}, [[функция высшего порядка|функции высшего порядка]], [[рекурсия#В программировании|рекурсивные определения функций]], оптимизацию [[хвостовая рекурсия|хвостовой рекурсии]]), модули{{Переход|#Модули}}, приём и отправку сообщений{{Переход|#Отправка и приём сообщений}} между процессами. Препроцессор{{Переход|#Препроцессор и макросы}} поддерживает работу с макросами и включение заголовочных файлов.


Популярность Erlang начала расти в связи с расширением его области применения ([[электросвязь|телекоммуникационные системы]]) на высоконагруженные параллельные распределённые системы, обслуживающие миллионы пользователей [[WWW]], такие как [[чат]]ы, [[система управления веб-содержимым|системы управления содержимым]], [[веб-сервер]]ы и распределённые, требующие масштабирования [[СУБД|базы данных]]. Erlang применяется в нескольких [[NoSQL]]-базах данных [[высокая доступность|высокой доступности]]{{sfn|Dan McCreary, Ann Kelly|2013|loc=10.3 Examples of functional programming languages}}.
Популярность Erlang начала расти в связи с расширением его области применения ([[электросвязь|телекоммуникационные системы]]) на высоконагруженные параллельные распределённые системы, обслуживающие миллионы пользователей [[WWW]], такие как [[Чат (программа)|чаты]], [[система управления веб-содержимым|системы управления содержимым]], [[веб-сервер]]ы и распределённые, требующие масштабирования [[СУБД|базы данных]]. Erlang применяется в нескольких [[NoSQL]]-базах данных [[высокая доступность|высокой доступности]]{{sfn|Dan McCreary, Ann Kelly|2013|loc=10.3 Examples of functional programming languages}}.


== История ==
== История ==
[[Файл:Robert Virding and Joe Armstrong, 2013.jpg|thumb|Роберт Вирдинг (слева) и [[Армстронг, Джо (программист)|Джо Армстронг]] в 2013 году]]
В середине 1980-х в компьютерной лаборатории компании [[Ericsson]] исследовали применимость существующих на тот момент языков программирования для программного обеспечения телекоммуникационных систем. Джо Армстронг (Joe Armstrong), Роберт Вирдинг (Robert Virding) и Майк Вильямс (Mike Williams) под руководством Бьярне Деккера (Bjarne Däcker), написав прототипы программ на различных языках, пришли к выводу, что ни один из этих языков не имел полного набора возможностей, необходимых в области телекоммуникационных систем. В результате был создан новый язык программирования — Erlang{{sfn|Чезарини, Томпсон|2012|с=25-26}}. Своё название язык, вероятно, получил в честь датского математика и инженера [[Эрланг, Агнер Краруп|Агнера Эрланга]], основателя научного направления по изучению [[сетевой трафик|сетевого трафика]] в телекоммуникационных системах. По другой версии, название языка изначально было сокращением от «ericsson language»{{sfn|Знакомьтесь, Erlang|2008}}.
В середине 1980-х годов в компьютерной лаборатории компании [[Ericsson]] исследовали применимость существовавших на тот момент языков программирования для программного обеспечения телекоммуникационных систем. [[Армстронг, Джо (программист)|Джо Армстронг]], Роберт Вирдинг (Robert Virding) и Майк Вильямс (Mike Williams) под руководством Бьярне Деккера (Bjarne Däcker), написав прототипы программ на различных языках, пришли к выводу, что ни один из этих языков не имел полного набора возможностей, необходимых в области телекоммуникационных систем. В результате был создан новый язык программирования — Erlang{{sfn|Чезарини, Томпсон|2012|с=25—26}}. Своё название язык, вероятно, получил в честь датского математика и инженера [[Эрланг, Агнер Краруп|Агнера Эрланга]], основателя научного направления по изучению [[сетевой трафик|сетевого трафика]] в телекоммуникационных системах. По другой версии, название языка изначально было сокращением от «Ericsson language»{{sfn|Знакомьтесь, Erlang|2009}}.


Влияние на Erlang оказали [[ML]], [[Миранда (язык программирования)|Миранда]], [[Ада (язык программирования)|Ада]], [[Модула-2]], [[CHILL]], [[Пролог (язык программирования)|Пролог]]. Кроме того, на способ обновления программного обеспечения повлиял [[Smalltalk]] и использованные Ericsson проприетарные языки EriPascal и PLEX{{sfn|Чезарини, Томпсон|2012|с=25-26}}.
Влияние на Erlang оказали [[ML]], [[Миранда (язык программирования)|Миранда]], [[Ада (язык программирования)|Ада]], [[Модула-2]], [[CHILL]], [[Пролог (язык программирования)|Пролог]]. Кроме того, на способ обновления программного обеспечения повлиял [[Smalltalk]] и использованные Ericsson проприетарные языки EriPascal и PLEX{{sfn|Чезарини, Томпсон|2012|с=25—26}}.


Потребовалось четыре года развития языка и прототипирования с использованием [[виртуальная машина|виртуальной машины]] Пролога, после чего в 1991 году Майк Вильямс переписал виртуальную машину для Erlang на Си. В 1992 году Erlang был впервые использован в коммерческом проекте{{sfn|Чезарини, Томпсон|2012|с=25-26}}. В 1995 году вышел новый [[релиз (программное обеспечение)|релиз]] Erlang, вобравший накопившийся к тому моменту опыт использования языка. Язык был сочтён достаточно развитым для использования в других продуктах компании (решения для широкополосной связи, [[GPRS]], [[ATM]]){{sfn|Чезарини, Томпсон|2012|с=25-26}}.
Потребовалось четыре года развития языка и прототипирования с использованием [[виртуальная машина|виртуальной машины]] Пролога, после чего в 1991 году Майк Вильямс переписал виртуальную машину для Erlang на Си. В 1992 году Erlang был впервые использован в коммерческом проекте{{sfn|Чезарини, Томпсон|2012|с=25—26}}. В 1995 году вышла новая версия Erlang, вобравшая накопившийся к тому моменту опыт использования языка. Язык был сочтён достаточно развитым для использования в других продуктах компании (решения для широкополосной связи, [[GPRS]], [[ATM]]){{sfn|Чезарини, Томпсон|2012|с=25—26}}.


В декабре 1995 года случилось событие, которое Джо Армстронг считает решающим для Erlang: проект AXE-N в Ellemtel по созданию нового маршрутизатора (как оборудования, так и системного программного обеспечения на C++) потерпел неудачу. В результате реорганизации проекта удалось, использовав разработанное оборудование и язык программирования Erlang, начать работы над ATM-маршрутизаторами серии AXD. Ресурсов лаборатории для такого проекта оказалось недостаточно, поэтому для работ по Erlang было создано производственное подразделение под названием OTP (Open Telecom Platform){{sfn|Armstrong, A History of Erlang|2007|loc=6-14}}. В 1996 году увидел свет одноимённый [[фреймворк]] OTP{{sfn|Чезарини, Томпсон|2012|с=25-26}}.
В декабре 1995 года случилось событие, которое Джо Армстронг считает решающим для Erlang: проект AXE-N в Ellemtel по созданию нового маршрутизатора (как оборудования, так и системного программного обеспечения на C++) потерпел неудачу. В результате реорганизации проекта удалось, использовав разработанное оборудование и язык программирования Erlang, начать работы над ATM-маршрутизаторами серии AXD. Ресурсов лаборатории для такого проекта оказалось недостаточно, поэтому для работ по Erlang было создано производственное подразделение под названием OTP (Open Telecom Platform){{sfn|Armstrong, A History of Erlang|2007|loc=6-14}}. В 1996 году увидел свет одноимённый [[фреймворк]] OTP{{sfn|Чезарини, Томпсон|2012|с=25—26}}.


Неожиданно{{sfn|Armstrong, A History of Erlang|2007|loc=6-16}}, в 1998 году [[топ-менеджмент]] Ericsson решил не брать на себя обязательства по разработке и поддержке собственного языка программирования, сосредоточившись вместо этого на [[Java]]. Использование Erlang было запрещено в новых проектах Ericsson Radio AB в связи с реализацией плана по [[аутсорсинг]]у программной технологии компании Rational Inc.{{sfn|Martin Logan, et al|2011|p=xxxi}}{{sfn|Bjarne Däcker, Master thesis|2011|loc=Backlash}} Это решение очень сильно повлияло на будущее Erlang: оно привело к открытию кода Erlang под [[Открытое программное обеспечение|открытой]] лицензией EPL (аналог [[Mozilla Public License]]){{sfn|Чезарини, Томпсон|2012|с=26}}, а также послужило главной причиной начала распространения языка за пределами создавшей его компании. Основным возражением против открытия исходного кода являлось решение вопросов, касающихся патентов, но эти трудности были преодолены{{sfn|Armstrong, A History of Erlang|2007|loc=6-17}}. Вскоре многие из основных разработчиков покинули Ericsson, чтобы организовать собственный бизнес — Bluetail AB{{sfn|Armstrong, A History of Erlang|2007|loc=6-17}}{{sfn|Martin Logan, et al|2011|p=xxxi}}.
Неожиданно{{sfn|Armstrong, A History of Erlang|2007|loc=6-16}}, в 1998 году [[топ-менеджмент]] Ericsson решил не брать на себя обязательств по разработке и поддержке собственного языка программирования, сосредоточившись вместо этого на [[Java]]. Использование Erlang было запрещено в новых проектах Ericsson Radio AB в связи с реализацией плана по [[аутсорсинг]]у программной технологии компании Rational Inc.{{sfn|Martin Logan, et al|2011|p=xxxi}}{{sfn|Bjarne Däcker, Master thesis|2000|loc=Backlash}} Это решение очень сильно повлияло на будущее Erlang: оно привело к открытию кода Erlang под [[Открытое программное обеспечение|открытой]] лицензией EPL (аналог [[Mozilla Public License]]){{sfn|Чезарини, Томпсон|2012|с=26}}, а также послужило главной причиной начала распространения языка за пределами создавшей его компании. Основным возражением против открытия исходного кода являлось решение вопросов, касающихся патентов, но эти трудности были преодолены{{sfn|Armstrong, A History of Erlang|2007|loc=6-17}}. Вскоре многие из основных разработчиков покинули Ericsson, чтобы организовать собственный бизнес — Bluetail AB{{sfn|Armstrong, A History of Erlang|2007|loc=6-17}}{{sfn|Martin Logan, et al|2011|p=xxxi}}.


В начале 2000-х учёные круги стали проявлять интерес к Erlang. С 2002 года стал проводиться ежегодный Erlang Workshop. Ericsson продолжал спонсирование проекта HiPE (от {{lang-en|High-Performance Erlang}} — высокопроизводительный Erlang){{sfn|Martin Logan, et al|2011|p=xxxii}} [[Уппсальский университет|уппсальского университета]]<ref group="Примечание">Сайт проекта: {{cite web|url=http://www.it.uu.se/research/group/hipe/|title=The High-Performance Erlang Project|publisher=Uppsala University}}</ref>. Проект HiPE занимался эффективной реализацией языка и инструментами для проверки типов, а с 2001 года созданный в группе проекта компилятор в машинный код входит в поставку свободно-распространяемой версии Erlang/OTP{{sfn|Armstrong, A History of Erlang|2007|loc=6-14}}. Работы, связанные с Erlang, ведут и другие высшие учебные заведения. Инструменты для [[рефакторинг]]а созданы в Кентском университете в Ве­ликобритании и [[Будапештский университет|университете Ло́ранда Э́твёша]] в Венгрии, инструменты для различных видов [[тестирование программного обеспечения|тестирования]] — в Мадридском политехническом университете, [[Технический университет Чалмерса|техническом университете Чалмерса]] и [[Гётеборгский университет|Гётеборгском универси­тете]]{{sfn|Чезарини, Томпсон|2012|с=24-25}}.
В начале 2000-х годов научные круги стали проявлять интерес к Erlang. С 2002 года стал проводиться ежегодный Erlang Workshop. Ericsson продолжал спонсирование проекта HiPE (от {{lang-en|High-Performance Erlang}} — высокопроизводительный Erlang){{sfn|Martin Logan, et al|2011|p=xxxii}} [[Уппсальский университет|уппсальского университета]]<ref group="Примечание">Сайт проекта: {{cite web |url=http://www.it.uu.se/research/group/hipe/ |title=The High-Performance Erlang Project |publisher=Uppsala University |accessdate=2013-12-06 |archiveurl=https://web.archive.org/web/20110616054408/http://www.it.uu.se/research/group/hipe/ |archivedate=2011-06-16 |deadlink=yes}}</ref>. Проект HiPE занимался эффективной реализацией языка и инструментами для проверки типов, а с 2001 года созданный в группе проекта компилятор в машинный код входит в поставку свободно распространяемой версии Erlang/OTP{{sfn|Armstrong, A History of Erlang|2007|loc=6-14}}. Работы, связанные с Erlang, ведут и другие высшие учебные заведения. Инструменты для [[рефакторинг]]а созданы в Кентском университете в Великобритании и [[Будапештский университет|университете Ло́ранда Э́твёша]] в Венгрии, инструменты для различных видов [[тестирование программного обеспечения|тестирования]] — в Мадридском политехническом университете, [[Технический университет Чалмерса|техническом университете Чалмерса]] и [[Гётеборгский университет|Гётеборгском университете]]{{sfn|Чезарини, Томпсон|2012|с=24—25}}.


Когда системы с симметричной многопроцессорностью только начинали завоёвывать рынок серверов и настольных компьютеров, бросая вызов разработчикам программного обеспечения, уже в 2006 году первая версия Erlang с поддержкой [[симметричная мультипроцессорность|SMP]] была выпущена совместными усилиями команды OTP из Ericsson и команды HiPE{{sfn|Martin Logan, et al|2011|p=xxxii}}. Вскоре после этого вышла первая почти за десятилетие крупная монография по Erlang: «Programming Erlang» Джо Армстронга{{sfn|Armstrong|2007}}, после чего многие разработчики «открыли» для себя Erlang/OTP{{sfn|Martin Logan, et al|2011|p=xxxii}}, и язык стал набирать популярность<ref>{{cite web|url=http://babel.ls.fi.upm.es/~fred/sbc/erlangia.pdf|title=Erlang – a platform for developing distributed software systems|author=Lars-Åke Fredlund|description=Component Based Software: 2011-2012, Universidad Politécnica de Madrid}}</ref>.
Когда системы с симметричной многопроцессорностью только начинали завоёвывать рынок серверов и настольных компьютеров, бросая вызов разработчикам программного обеспечения, уже в 2006 году первая версия Erlang с поддержкой [[симметричная многопроцессорность|SMP]] была выпущена совместными усилиями команды OTP из Ericsson и команды HiPE{{sfn|Martin Logan, et al|2011|p=xxxii}}. Вскоре после этого вышла первая почти за десятилетие крупная монография по Erlang: «Programming Erlang» Джо Армстронга{{sfn|Armstrong|2007}}, после чего многие разработчики «открыли» для себя Erlang/OTP{{sfn|Martin Logan, et al|2011|p=xxxii}}, и язык стал набирать популярность<ref>{{cite web |url=http://babel.ls.fi.upm.es/~fred/sbc/erlangia.pdf |title=Erlang – a platform for developing distributed software systems |author=Lars-Åke Fredlund |description=Component Based Software: 2011—2012, Universidad Politécnica de Madrid |access-date=2013-12-06 |archive-date=2012-10-19 |archive-url=https://web.archive.org/web/20121019041623/http://babel.ls.fi.upm.es/~fred/sbc/erlangia.pdf |deadlink=no }}</ref>.


Процесс развития языка включает в себя рассмотрение предложений по развитию — EEP ({{lang-en|Erlang Enhancement Proposal}}). Через эти предложения Erlang-сообщество вносит изменения в стандартную поставку Erlang{{sfn|Чезарини, Томпсон|2012|с=381}}. С внесёнными предложениями можно ознакомиться на веб-странице erlang.org/eeps<ref>{{cite web|url=http://www.erlang.org/eeps/|title=EEP 0: Index of Erlang Enhancement Proposals (EEPs)| publisher=|date=31-05-2007|licence=Public Domain}}</ref>.
Процесс развития языка включает в себя рассмотрение предложений по развитию — EEP ({{lang-en|Erlang Enhancement Proposal}}). Через эти предложения Erlang-сообщество вносит изменения в стандартную поставку Erlang{{sfn|Чезарини, Томпсон|2012|с=381}}. С внесёнными предложениями можно ознакомиться на веб-странице erlang.org/eeps<ref>{{cite web |url=http://www.erlang.org/eeps/ |title=EEP 0: Index of Erlang Enhancement Proposals (EEPs) |publisher= |date=2007-05-31 |access-date=2013-12-01 |archive-date=2013-10-01 |archive-url=https://web.archive.org/web/20131001140700/http://www.erlang.org/eeps/ |deadlink=no }}</ref>.


== Философия ==
== Философия ==
По свидетельству Майка Вильямса, Erlang задумывался для решения трёх проблем разработки [[распределённая система|распределённых]] [[Операционная система реального времени#Системы жёсткого и мягкого реального времени|систем мягкого реального времени]] с высокой степенью [[параллелизм (информатика)|параллелизма]]: возможности быстрой и эффективной разработки ПО; получения системы, устойчивой к программным и аппаратным сбоям и возможности обновления системы «на лету», без простоя оборудования{{sfn|Чезарини, Томпсон|2012|с=15}}.
По свидетельству Майка Вильямса, Erlang задумывался для решения трёх проблем разработки [[распределённая система|распределённых]] [[Операционная система реального времени#Системы жёсткого и мягкого реального времени|систем мягкого реального времени]] с высокой степенью [[параллелизм (информатика)|параллелизма]]: возможности быстрой и эффективной разработки ПО; получения системы, устойчивой к программным и аппаратным сбоям, и возможности обновления системы «на лету», без простоя оборудования{{sfn|Чезарини, Томпсон|2012|с=15}}.


По словам Вильямса, философия, которой придерживались разработчики Erlang, подходит и для разработки программного обеспечения на этом языке{{sfn|Cesarini, Thompson|2009|p=14}}<!-- в рус. изд. перевод 3-го пункта странен -->:
По словам Вильямса, философия, которой придерживались разработчики Erlang, подходит и для разработки программного обеспечения на этом языке{{sfn|Cesarini, Thompson|2009|p=14}}<!-- в рус. изд. перевод 3-го пункта странен -->:
{{начало цитаты}}
{{начало цитаты}}
* Найдите наиболее подходящие методы. Проектируйте с использованием прототипов;
* Найдите наиболее подходящие методы. Проектируйте с использованием прототипов;
* Одних идей мало: нужно уметь их реализовать и знать, как они работают;
* Одних идей мало: нужно уметь их реализовать и знать, что они работают;
* Делайте ошибки в небольшом масштабе, а не в производственном проекте.
* Делайте ошибки в небольшом масштабе, а не в производственном проекте.
{{oq|en|
{{oq|en|
Строка 55: Строка 46:
}}{{конец цитаты}}
}}{{конец цитаты}}


Большинство языков, созданных прежде Erlang, были разработаны без предварительного нахождения своей области применения, тогда как Erlang был разработан специально на основе требований к распределённым, отказоустойчивым, параллельным системам реального времени. С развитием сети Интернет оказалось, что многие приложения имеют аналогичные требования{{sfn|Чезарини, Томпсон|2012|с=26}}, чем и объясняется растущий интерес к языку{{sfn|Simon St. Laurent|2013|с=vii}}.
Большинство языков, созданных прежде Erlang, было разработано без предварительного нахождения своей области применения, тогда как Erlang был разработан специально на основе требований к распределённым, отказоустойчивым, параллельным системам реального времени. С развитием сети Интернет оказалось, что многие приложения имеют аналогичные требования{{sfn|Чезарини, Томпсон|2012|с=26}}, чем и объясняется растущий интерес к языку{{sfn|Simon St. Laurent|2013|с=vii}}.


Высокая отказоустойчивость кроется в применении изолированных друг от друга легковесных процессов, связанных лишь механизмом обмена сообщениями и сигналами выхода. Принцип разработчиков на Erlang по отношению к обработке ошибочных ситуаций в процессах{{Переход|#Обработка ошибок в процессах}} можно выразить в виде высказывания:
Высокая отказоустойчивость кроется в применении изолированных друг от друга легковесных процессов, связанных лишь механизмом обмена сообщениями и сигналами выхода. Принцип разработчиков на Erlang по отношению к обработке ошибочных ситуаций в процессах{{Переход|#Обработка ошибок в процессах}} можно выразить в виде высказывания:
{{начало цитаты}}Позвольте приложению упасть, и пускай кто-то другой займётся им{{sfn|Чезарини, Томпсон|2012|с=167}}
{{начало цитаты}}Позвольте приложению упасть, и пускай что-то другое имеет с этим дело.{{sfn|Чезарини, Томпсон|2012|с=167}}
{{oq|en|Let it crash and let someone else deal with it}}{{конец цитаты}}
{{oq|en|Let it crash and let someone else deal with it}}{{конец цитаты}}
или сокращённо — «let it crash» («пусть падает»). Связано это с тем, что в Erlang-системе легко следить за завершением процесса, завершать процессы, связанные со сбойным, и запускать новые процессы{{sfn|Tate|2010|p=183}}.
или сокращённо — «let it crash» («пусть падает»). Связано это с тем, что в Erlang-системе легко следить за завершением процесса, завершать процессы, связанные со сбойным, и запускать новые процессы{{sfn|Tate|2010|p=183}}.
Строка 65: Строка 56:


=== Высокоуровневые конструкции ===
=== Высокоуровневые конструкции ===
Erlang является [[декларативный язык программирования|декларативным языком программирования]], который скорее используется для описания того, ''что'' должно быть вычислено нежели ''как''. Например, определение функции{{Переход|#Функции}}, которое использует [[сопоставление с образцом]]{{Переход|#Сопоставление с образцом}} для выбора одного из вариантов вычисления или извлечения элемента данных из составной структуры, напоминает [[уравнение]]. Сопоставление с образцом распространено даже на битовые строки{{Переход|#Битовые строки и бинарные данные}}, что упрощает реализацию телекоммуникационных протоколов{{sfn|Чезарини, Томпсон|2012|с=26}}.
Erlang является [[декларативный язык программирования|декларативным языком программирования]], который скорее используется для описания того, ''что'' должно быть вычислено, нежели того,''как''. Например, определение функции{{Переход|#Функции}}, которое использует [[сопоставление с образцом]]{{Переход|#Сопоставление с образцом}} для выбора одного из вариантов вычисления или извлечения элемента данных из составной структуры напоминает [[уравнение]]. Сопоставление с образцом распространено даже на битовые строки{{Переход|#Битовые строки и бинарные данные}}, что упрощает реализацию телекоммуникационных протоколов{{sfn|Чезарини, Томпсон|2012|с=26}}.


[[Функция (программирование)|Функции]] являются [[объект первого класса|объектами первого класса]] в Erlang. В языке также широко применяются характерные для [[функциональное программирование|функциональной парадигмы]] программирования [[списковое включение|списковые включения]] (генераторы списков){{sfn|Чезарини, Томпсон|2012|с=27}}.
[[Функция (программирование)|Функции]] являются [[объект первого класса|объектами первого класса]] в Erlang. В языке также широко применяются характерные для [[функциональное программирование|функциональной парадигмы]] программирования [[списковое включение|списковые включения]] (генераторы списков){{sfn|Чезарини, Томпсон|2012|с=27}}.
Строка 71: Строка 62:
=== Параллельные вычисления ===
=== Параллельные вычисления ===
[[Файл:Erlang.png|мини|500px|Обмен сообщениями между процессами в Erlang]]
[[Файл:Erlang.png|мини|500px|Обмен сообщениями между процессами в Erlang]]
Отличительной особенностью языка является применение [[легковесный процесс|легковесных процессов]] в соответствии с [[модель акторов|моделью акторов]]. Такой подход позволяет выполнять одновременно сотни тысяч и даже миллионы таких процессов, каждый из которых может иметь скромные требования по [[ОЗУ|памяти]]{{sfn|Чезарини, Томпсон|2012|с=117}}. Процессы изолированы друг от друга и не имеют общего состояния, но между ними можно установить связь и получать сообщения об их состоянии. Для взаимодействия процессов используется асинхронный обмен сообщениями. Каждый процесс имеет свою [[очередь (программирование)|очередь]] сообщений, обработка которой использует сопоставление с образцом. Процесс, отправивший сообщение, не получает уведомления о доставке, даже если идентификатор процесса-получателя недействителен или получатель игнорирует сообщение. Таким образом, ответственность за правильно организованное взаимодействие между процессами лежит на разработчике{{sfn|Simon St. Laurent|2013|с=88}}.
Отличительной особенностью языка является применение '''''легковесных процессов''''' в соответствии с [[модель акторов|моделью акторов]]. Такой подход позволяет выполнять одновременно сотни тысяч и даже миллионы таких процессов, каждый из которых может иметь скромные требования по [[ОЗУ|памяти]]{{sfn|Чезарини, Томпсон|2012|с=117}}. Процессы изолированы друг от друга и не имеют общего состояния, но между ними можно установить связь и получать сообщения об их состоянии. Для взаимодействия процессов используется асинхронный обмен сообщениями. Каждый процесс имеет свою [[очередь (программирование)|очередь]] сообщений, обработка которой использует сопоставление с образцом. Процесс, отправивший сообщение, не получает уведомления о доставке, даже если идентификатор процесса-получателя недействителен или получатель игнорирует сообщение. Таким образом, ответственность за правильно организованное взаимодействие между процессами лежит на разработчике{{sfn|Simon St. Laurent|2013|с=88}}.


Например, при реализация на Erlang сетевого [[чат]]а структура программы может напрямую отражать одновременность действий пользователей по обмену сообщениями путём запуска новых процессов. Эффективность передачи сообщений сохраняется и при увеличении числа процессов, а требования к памяти минимизируются за счёт того, что легковесными процессами управляет виртуальная машина, а не средства нижележащей операционной системы{{sfn|Чезарини, Томпсон|2012|с=117-118}}.
Например, при реализации на Erlang сетевого [[Чат (программа)|чата]] структура программы может напрямую отражать одновременность действий пользователей по обмену сообщениями путём запуска новых процессов. Эффективность передачи сообщений сохраняется и при увеличении числа процессов, а требования к памяти минимизируются за счёт того, что легковесными процессами управляет виртуальная машина, а не средства нижележащей операционной системы{{sfn|Чезарини, Томпсон|2012|с=117—118}}.


=== Распределённые вычисления ===
=== Распределённые вычисления ===
Erlang с самого начала проектировался для [[распределённые вычисления|распределённых вычислений]] и [[масштабируемость|масштабируемости]]. Распределение вычислений встроено в синтаксис и семантику языка, поэтому построение системы можно вести, абстрагируясь от конкретного места вычислений. В стандартной поставке Erlang может наладить связь процессов по протоколу [[TCP/IP]] независимо от поддерживаемых им нижележащих платформ ([[операционная система|операционных систем]]){{sfn|Чезарини, Томпсон|2012|с=30-31}}.
Erlang с самого начала проектировался для [[распределённые вычисления|распределённых вычислений]] и [[масштабируемость|масштабируемости]]. Распределение вычислений встроено в синтаксис и семантику языка, поэтому построение системы можно вести, абстрагируясь от конкретного места вычислений. В стандартной поставке Erlang может наладить связь процессов по протоколу [[TCP/IP]] независимо от поддерживаемых им нижележащих платформ ([[операционная система|операционных систем]]){{sfn|Чезарини, Томпсон|2012|с=30—31}}.


Работающий экземпляр [[рантайм|среды выполнения]] Erlang ({{lang-en|Erlang runtime system}}) называется '''''узлом''''' ({{lang-en|node}}). Программы, написанные на Erlang, способны работать на нескольких узлах. Узлами могут быть процессоры, многие [[ядро микропроцессора|ядра]] одного процессора, и даже целый кластер машин. Узел имеет имя и «знает» о существовании других узлов на данной машине или в сети. Создание и взаимодействие процессов разных узлов не отличается от организации взаимодействия процессов внутри узла. Для создания процесса на другом узле процессу достаточно знать его имя и, без особых на то оснований, он может не интересоваться физическим расположением взаимодействующего с ним процесса. Синтаксис отправки сообщения процессу на своём узле и удалённом один и тот же{{sfn|Чезарини, Томпсон|2012|с=30-31}}.
Работающий экземпляр [[рантайм|среды выполнения]] Erlang ({{lang-en|Erlang runtime system}}) называется '''''узлом''''' ({{lang-en|node}}). Программы, написанные на Erlang, способны работать на нескольких узлах. Узлами могут быть процессоры, многие [[ядро микропроцессора|ядра]] одного процессора, и даже целый кластер машин. Узел имеет имя и «знает» о существовании других узлов на данной машине или в сети. Создание и взаимодействие процессов разных узлов не отличается от организации взаимодействия процессов внутри узла. Для создания процесса на другом узле процессу достаточно знать его имя и, без особых на то оснований, он может не интересоваться физическим расположением взаимодействующего с ним процесса. Синтаксис отправки сообщения процессу на своём узле и удалённом — один и тот же{{sfn|Чезарини, Томпсон|2012|с=30—31}}.


Благодаря встроенным в язык возможностям распределённых вычислений объединение в [[кластер (группа компьютеров)|кластер]], [[балансировка нагрузки]], добавление узлов и серверов, повышение надёжности вызывают лишь небольшие затраты на дополнительный код. [[По умолчанию]] узлы спроектированы для работы внутри обособленного сегмента сети ([[DMZ (компьютерные сети)|DMZ]]), но, если необходимо, коммуникация между узлами может происходить с применением защищённого криптографическими методами протокола [[SSL]]{{sfn|Чезарини, Томпсон|2012|с=30-31}}.
Благодаря встроенным в язык возможностям распределённых вычислений объединение в [[кластер (группа компьютеров)|кластер]], [[балансировка нагрузки]], добавление узлов и серверов, повышение надёжности вызывают лишь небольшие затраты на дополнительный код. [[По умолчанию]] узлы спроектированы для работы внутри обособленного сегмента сети ([[DMZ (компьютерные сети)|DMZ]]), но, если необходимо, коммуникация между узлами может происходить с применением защищённого криптографическими методами протокола [[SSL]]{{sfn|Чезарини, Томпсон|2012|с=30—31}}.


=== Мягкое реальное время ===
=== Мягкое реальное время ===
Программы на высокоуровневом языке Erlang могут быть использованы в системах [[реальное время|мягкого реального времени]] (которое иногда переводят как «псевдореальное» или «квазиреальное»{{sfn|Чезарини, Томпсон|2012|с=23-24}}). Автоматизированное управление памятью и [[сборка мусора (программирование)|сборка мусора]] действуют в рамках одного процесса, что даёт возможность создавать системы с миллисекундным [[время отклика|временем отклика]] (даже несмотря на необходимость сборки мусора), не испытывающие ухудшения пропускной способности при высокой нагрузке{{sfn|Чезарини, Томпсон|2012|с=29}}.
Программы на высокоуровневом языке Erlang могут быть использованы в системах [[реальное время|мягкого реального времени]] (которое иногда переводят как «псевдореальное» или «квазиреальное»{{sfn|Чезарини, Томпсон|2012|с=23—24}}). Автоматизированное управление памятью и [[сборка мусора (программирование)|сборка мусора]] действуют в рамках одного процесса, что даёт возможность создавать системы с миллисекундным [[время отклика|временем отклика]] (даже несмотря на необходимость сборки мусора), не испытывающие ухудшения пропускной способности при высокой нагрузке{{sfn|Чезарини, Томпсон|2012|с=29}}.


=== Горячая замена кода ===
=== Горячая замена кода ===
Для систем, которые не могут быть остановлены для [[Обновление программного обеспечения|обновления кода]], Erlang предлагает горячую замену кода ({{lang-en|hot code upgrade}}). При этом в приложении могут одновременно работать старая и новая версии кода. Таким способом программное обеспечение на Erlang может быть модернизировано без простоев, а выявленные ошибки исправлены{{sfn|Знакомьтесь, Erlang|2008}}<ref name="whitepaper">{{cite web|url=http://ftp.sunet.se/pub/lang/erlang/white_paper.html|title=Open-source Erlang — White Paper|date=2013|author=Joe Armstrong, Bjarne Däcker, Thomas Lindgren, Håkan Millroth, Erlang product team at Ericsson|publisher=Ericsson AB|accessdate=|lang=en}}</ref>.
Для систем, которые не могут быть остановлены для обновления кода, Erlang предлагает горячую замену кода ({{lang-en|hot code upgrade}}). При этом в приложении могут одновременно работать старая и новая версии кода. Таким способом программное обеспечение на Erlang может быть модернизировано без простоев, а выявленные ошибки исправлены{{sfn|Знакомьтесь, Erlang|2009}}<ref name="whitepaper">{{cite web|url=http://ftp.sunet.se/pub/lang/erlang/white_paper.html|title=Open-source Erlang — White Paper|date=2013|author=Joe Armstrong, Bjarne Däcker, Thomas Lindgren, Håkan Millroth, Erlang product team at Ericsson|publisher=Ericsson AB|accessdate=|lang=en|archiveurl=https://web.archive.org/web/20111025022940/http://ftp.sunet.se/pub/lang/erlang/white_paper.html|archivedate=2011-10-25}}</ref>.


== Описание языка ==
== Описание языка ==


=== Типы данных ===
=== Типы данных ===
Типизация в Erlang является [[строгая типизация|строгой]] и [[динамическая типизация|динамической]]. Динамическая типизация была выбрана для языка Erlang по причине того, что первые разработчики были больше с ней знакомы{{sfn|Hebert|2013|loc=Types (or lack thereof)}}. По мнению Джо Армстронга, статическая типизация потребовала бы очень больших трудозатрат, в частности, реализовать систему горячей дозагрузки кода было бы крайне затруднительно{{sfn|Чезарини, Томпсон|2012|с=39}}. Такая типизация, при которой возможные ошибки типов выявляются только во время выполнения, тем не менее, не помешала создавать системы с очень [[высокая доступность|высоким уровнем доступности]]{{sfn|Hebert|2013|loc=Types (or lack thereof)}}. Данные в Erlang являются ''неизменяемыми'': операции не переписывают старые значения, находящиеся в памяти. Если необходимо, модули на Erlang можно снабдить описаниями и определениями новых типов (не влияющими на компиляцию программы) для автоматической проверки типов с помощью утилиты Dialyzer{{sfn|Hebert|2013|loc=Type Specifications and Erlang}}.
Типизация в Erlang является [[сильная типизация|сильной]] и [[динамическая типизация|динамической]]. Динамическая типизация была выбрана для языка Erlang по причине того, что первые разработчики были больше с ней знакомы{{sfn|Hebert|2013|loc=Types (or lack thereof)}}. По мнению Джо Армстронга, статическая типизация потребовала бы очень больших трудозатрат, в частности, реализовать систему горячей дозагрузки кода было бы крайне затруднительно{{sfn|Чезарини, Томпсон|2012|с=39}}. Такая типизация, при которой возможные ошибки типов выявляются только во время выполнения, тем не менее, не помешала создавать системы с очень [[высокая доступность|высоким уровнем доступности]]{{sfn|Hebert|2013|loc=Types (or lack thereof)}}. Данные в Erlang являются ''неизменяемыми'': операции не переписывают старые значения, находящиеся в памяти. Если необходимо, модули на Erlang можно снабдить описаниями и определениями новых типов (не влияющими на компиляцию программы) для автоматической проверки типов с помощью утилиты Dialyzer{{sfn|Hebert|2013|loc=Type Specifications and Erlang}}.


==== Числа ====
==== Числа ====
В Erlang есть два типа числовых [[литерал (информатика)|литералов]]: ''целые'' и с ''плавающей запятой'', например: <code>4.5e-20</code>, <code>125</code>. Кроме обычной нотации, числа можно задавать через символ [[ASCII]] (например, <code>$B</code> означает <code>66</code>) или вместе с указанием системы счисления с основанием от 2 до 36 (в старых версиях — до 16), например: <code>16#3f</code>, <code>2#1010</code>. В Erlang применяются целые числа [[арифметика произвольной точности|произвольной точности]] и действительные числа двойной точности (64 [[бит]]а), в стандарте [[IEEE 754-2008|IEEE 754—1985]]{{sfn|Чезарини, Томпсон|2012|с=38-39}}.
В Erlang есть два типа числовых [[литерал (информатика)|литералов]]: ''целые'' и с ''плавающей запятой'', например: <code>125</code>, <code>4.5e-20</code>. Кроме обычной нотации, числа можно задавать через символ [[ASCII]] (например, <code>$B</code> означает <code>66</code>) или вместе с указанием системы счисления с основанием от 2 до 36 (в старых версиях — до 16), например: <code>16#3f</code>, <code>2#1010</code>. В Erlang применяются целые числа [[арифметика произвольной точности|произвольной точности]] и действительные числа двойной точности (64 [[бит]]а), в стандарте [[IEEE 754-2008|IEEE 754—1985]]{{sfn|Чезарини, Томпсон|2012|с=38—39}}.


Для работы с числами можно использовать модуль <code>math</code>, который содержит обычный набор математических функций и функцию <code>math:pi/0</code>, возвращающую [[Пи (число)|число <math>\pi</math>]]<ref>{{cite web|url=http://www.erlang.org/doc/man/math.html|title=math, STDLIB Reference Manual Version 1.19.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en}}</ref>. Пример вычислений в интерактивной оболочке{{Переход|#Интерактивная оболочка}}:
Для работы с числами можно использовать модуль <code>math</code>, который содержит обычный набор математических функций и функцию <code>math:pi/0</code>, возвращающую [[Пи (число)|число <math>\pi</math>]]<ref>{{cite web|url=http://www.erlang.org/doc/man/math.html|title=math, STDLIB Reference Manual Version 1.19.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en|archive-date=2013-12-02|archive-url=https://web.archive.org/web/20131202235908/http://www.erlang.org/doc/man/math.html|deadlink=no}}</ref>. Пример вычислений в интерактивной оболочке{{Переход|#Интерактивная оболочка}}:
<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:4:4] [async-threads:0] [kernel-poll:false]
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:4:4] [async-threads:0] [kernel-poll:false]
Строка 110: Строка 101:


==== Атомы ====
==== Атомы ====
''Атом'' — константа с именем, которая должна быть заключена в одинарные кавычки, если не начинается со строчной буквы или содержит знаки, кроме букв, цифр, подчёркивания, точки и символа <code>@</code>. Понятие атома заимствовано из Пролога и его можно считать аналогом [[перечисляемый тип|перечислений]] (enum) в других языках программирования (без необходимости предварительной декларации){{sfn|Martin Logan, et al|2011|p=31-32}}. Атомы используются почти исключительно в сравнениях, имеющих в Erlang очень эффективную реализацию{{sfn|Чезарини, Томпсон|2012|с=41-42}}. Кроме того, некоторые атомы имеют определённый смысл в возращаемых значениях и описании исключений. К ним относятся: <code>error</code>, <code>ignore</code>, <code>noreply</code>, <code>ok</code>, <code>reply</code>, <code>stop</code>, <code>undefined</code>{{sfn|Simon St. Laurent|2013|с=172}}.
''Атом'' — константа с именем, которая должна быть заключена в одинарные кавычки, если не начинается со строчной буквы или содержит знаки, кроме букв, цифр, подчёркивания, точки и символа <code>@</code>. Понятие атома заимствовано из Пролога и его можно считать аналогом [[перечисляемый тип|перечислений]] (enum) в других языках программирования (без необходимости предварительной декларации){{sfn|Martin Logan, et al|2011|p=31—32}}. Атомы используются почти исключительно в сравнениях, имеющих в Erlang очень эффективную реализацию{{sfn|Чезарини, Томпсон|2012|с=41—42}}. Кроме того, некоторые атомы имеют определённый смысл в возвращаемых значениях и описании исключений. К ним относятся: <code>error</code>, <code>ignore</code>, <code>noreply</code>, <code>ok</code>, <code>reply</code>, <code>stop</code>, <code>undefined</code>{{sfn|Simon St. Laurent|2013|с=172}}.


==== Битовые строки и бинарные данные ====
==== Битовые строки и бинарные данные ====
''Битовая строка'' используется для хранения в памяти нетипизированных данных. Строки, состоящие из целого количества [[октет (информатика)|октетов]], называются ''бинарными'' (или ''двоичными'') ''данными'' ({{lang-en|binaries}}). Синтаксис описания битовой строки довольно гибок, так как описывает значения битов отдельных диапазонов и может быть снабжён модификатором типа{{sfn|Чезарини, Томпсон|2012|с=230-235}}. Несколько примеров в интерактивной командной оболочке:
''Битовая строка'' используется для хранения в памяти нетипизированных данных. Строки, состоящие из целого количества [[октет (информатика)|октетов]], называются ''бинарными'' (или ''двоичными'') ''данными'' ({{lang-en|binaries}}). Синтаксис описания битовой строки довольно гибок, так как описывает значения битов отдельных диапазонов и может быть снабжён модификатором типа{{sfn|Чезарини, Томпсон|2012|с=230—235}}. Несколько примеров в интерактивной командной оболочке:


<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
Строка 121: Строка 112:
<<65,66,67>>
<<65,66,67>>
3> <<10,17,42:16>>.
3> <<10,17,42:16>>.
<<1,17,0,42>>
<<10,17,0,42>>
4> <<$a, $b, $c>>.
4> <<$a, $b, $c>>.
<<"abc">>
<<"abc">>
Строка 128: Строка 119:
</syntaxhighlight>
</syntaxhighlight>


Выражения битовых строк ({{lang-en|bitstring comprehension}}) аналогичны списковым включениям, но работают над битовыми строками{{sfn|Чезарини, Томпсон|2012|с=233-234}}:
Выражения битовых строк ({{lang-en|bitstring comprehension}}) аналогичны списковым включениям, но работают над битовыми строками{{sfn|Чезарини, Томпсон|2012|с=233—234}}:


<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
Строка 138: Строка 129:


==== Кортеж ====
==== Кортеж ====
''[[Кортеж (информатика)#В программировании|Кортеж]]'' ({{lang-en|tuple}}) — составной тип данных с фиксированным количеством элементов. При доступе к элементам кортежа с помощью встроенных функций нумерация элементов начинается с единицы, а не с нуля. Первый элемент кортежа принято использовать для указания роли кортежа в программе. Если первый элемент — атом, его называют тегом ({{lang-en|tag}} — «метка»). В Erlang принято строить различные типы данных на основе кортежей с тегами, что облегчает отладку программы и считается хорошим стилем программирования{{sfn|Чезарини, Томпсон|2012|с=44-45}}.
''[[Кортеж (информатика)#В программировании|Кортеж]]'' ({{lang-en|tuple}}) — составной тип данных с фиксированным количеством элементов. При доступе к элементам кортежа с помощью встроенных функций нумерация элементов начинается с единицы, а не с нуля. Первый элемент кортежа принято использовать для указания роли кортежа в программе. Если первый элемент — атом, его называют тегом ({{lang-en|tag}} — «метка»). В Erlang принято строить различные типы данных на основе кортежей с тегами, что облегчает отладку программы и считается хорошим стилем программирования{{sfn|Чезарини, Томпсон|2012|с=44—45}}.


Для работы с кортежами есть несколько встроенных функций, например{{sfn|Чезарини, Томпсон|2012|с=44-45}}:
Для работы с кортежами есть несколько встроенных функций, например{{sfn|Чезарини, Томпсон|2012|с=44—45}}:


<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
Строка 152: Строка 143:


==== Список ====
==== Список ====
''Список'' ({{lang-en|list}}) — составной тип данных, содержащий переменное число элементов. Для манипуляции со списками можно применять функции модуля <code>lists</code> стандартной библиотеки{{sfn|Чезарини, Томпсон|2012|с=48-51}}. Формально список определяется как имеющий голову ({{lang-en|head}}) и хвост ({{lang-en|tail}}), что выражается синтаксически в виде <code>[HEAD|TAIL]</code>, где хвост обычно является списком (возможно, пустым). Пустой список обозначается <code>[]</code>{{sfn|Чезарини, Томпсон|2012|с=47-48}}.
''Список'' ({{lang-en|list}}) — составной тип данных, содержащий переменное число элементов. Для манипуляции со списками можно применять функции модуля <code>lists</code> стандартной библиотеки{{sfn|Чезарини, Томпсон|2012|с=48—51}}. Формально список определяется как имеющий голову ({{lang-en|head}}) и хвост ({{lang-en|tail}}), что выражается синтаксически в виде <code>[HEAD|TAIL]</code>, где хвост обычно является списком (возможно, пустым). Пустой список обозначается <code>[]</code>{{sfn|Чезарини, Томпсон|2012|с=47—48}}.


Списки можно записывать и более привычным способом. Следующие записи эквивалентны:
Списки можно записывать и более привычным способом. Следующие записи эквивалентны:
Строка 168: Строка 159:
</syntaxhighlight>
</syntaxhighlight>


Модуль <code>lists</code> стандартной библиотеки{{Переход|#Стандартная библиотека модулей}} содержит функции для обработки списков (и строк, так как в Erlang строка является списком){{sfn|Чезарини, Томпсон|2012|с=48-50}}, такие как нахождение максимума, сортировка, изменение порядка элементов на противоположный, суммирование элементов и т. п. В следующем примере два списка склеиваются операцией конкатенации, а затем разбиваются на две части функцией <code>lists:split/2</code>:
Модуль <code>lists</code> стандартной библиотеки{{Переход|#Стандартная библиотека модулей}} содержит функции для обработки списков (и строк, так как в Erlang строка является списком){{sfn|Чезарини, Томпсон|2012|с=48—50}}, такие как нахождение максимума, сортировка, изменение порядка элементов на противоположный, суммирование элементов и т. п. В следующем примере два списка склеиваются операцией конкатенации, а затем разбиваются на две части функцией <code>lists:split/2</code>:


<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
Строка 186: Строка 177:
</syntaxhighlight>
</syntaxhighlight>


Результат выполнения свёртки справа налево (в строке 2) тождественен цепочечному делению (строка 3). Второй параметр <code>foldr</code> даёт начальное значение для так называемого аккумулятора. Для каждого элемента списка (справа налево) к элементу и аккумулятору применяется функция, заданная первым аргументом <code>foldr</code>, а значение записывается в аккумулятор. По исчерпанию списка функция возвращает значение аккумулятора{{sfn|Чезарини, Томпсон|2012|с=223}}. Функция является достаточно мощным средством, если учесть, что аккумулятор может быть списком или кортежем{{sfn|Simon St. Laurent|2013|с=84-85}}.
Результат выполнения свёртки справа налево (в строке 2) тождественен цепочечному делению (строка 3). Второй параметр <code>foldr</code> даёт начальное значение для так называемого аккумулятора. Для каждого элемента списка (справа налево) к элементу и аккумулятору применяется функция, заданная первым аргументом <code>foldr</code>, а значение записывается в аккумулятор. По исчерпанию списка функция возвращает значение аккумулятора{{sfn|Чезарини, Томпсон|2012|с=223}}. Функция является достаточно мощным средством, если учесть, что аккумулятор может быть списком или кортежем{{sfn|Simon St. Laurent|2013|с=84—85}}.


==== Строка ====
==== Строка ====
Строка 216: Строка 207:


==== Запись ====
==== Запись ====
Чтобы помечать отдельные элементы кортежей и избежать ошибок при написании программы, в Erlang был внесён синтаксис ''[[запись (тип данных)|записей]]'' ({{lang-en|record}}). Для работы с записями, необходимо в начале дать описание записи директивой <code>-record</code>, например, для записи <code>user</code> описание может быть следующим{{sfn|Martin Logan, et al|2011|p=69-71}}:
Чтобы помечать отдельные элементы кортежей и избежать ошибок при написании программы, в Erlang был внесён синтаксис ''[[запись (тип данных)|записей]]'' ({{lang-en|record}}). Для работы с записями, необходимо в начале дать описание записи директивой <code>-record</code>, например, для записи <code>user</code> описание может быть следующим{{sfn|Martin Logan, et al|2011|p=69—71}}:


<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
Строка 224: Строка 215:
Из этого описания компилятор узнаёт, что имеются в виду кортежи из четырёх элементов, в которых элементы со второго по четвёртый соответствуют полям <code>login</code>, <code>password</code>, <code>nick</code> (порядок важен) записи с именем <code>user</code> (определяется атомом в первом элементе кортежа). Значением по умолчанию для поля <code>login</code> является строка <code>"anon"</code>. Если значение по умолчанию не указано явно, подразумевается атом <code>undefined</code>.
Из этого описания компилятор узнаёт, что имеются в виду кортежи из четырёх элементов, в которых элементы со второго по четвёртый соответствуют полям <code>login</code>, <code>password</code>, <code>nick</code> (порядок важен) записи с именем <code>user</code> (определяется атомом в первом элементе кортежа). Значением по умолчанию для поля <code>login</code> является строка <code>"anon"</code>. Если значение по умолчанию не указано явно, подразумевается атом <code>undefined</code>.


Создание записей и извлечение элементов записи всегда требует явного указания имени записи{{sfn|Martin Logan, et al|2011|p=69-71}}:
Создание записей и извлечение элементов записи всегда требует явного указания имени записи{{sfn|Martin Logan, et al|2011|p=69—71}}:


<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
Строка 231: Строка 222:
</syntaxhighlight>
</syntaxhighlight>


Синтаксис доступа к значениям полей записи: <code>R1#user.login</code>, <code>R0#user.nick</code>{{sfn|Martin Logan, et al|2011|p=69-71}}.
Синтаксис доступа к значениям полей записи: <code>R1#user.login</code>, <code>R0#user.nick</code>{{sfn|Martin Logan, et al|2011|p=69—71}}.

==== Ассоциативный массив ====
[[Ассоциативный массив|Ассоциативный массив (словарь)]] хранит пары вида «(ключ, значение)». В качестве как ключа, так и значения, может выступать любой терм Erlang.

<syntaxhighlight lang="Erlang">
Map = #{a => 2, b => 3, c=> 4, "a" => 1, "b" => 2, "hi" => 42},
Key = "hi",
maps:find(Key,Map).
{ok,42}
</syntaxhighlight>


==== Другие типы ====
==== Другие типы ====
В языке Erlang имеются и другие типы данных. Тип ''ссылка'' ({{lang-en|reference}}) является практически уникальной в среде времени выполнения Erlang<ref name="datatypes">{{cite web|url=http://www.erlang.org/doc/reference_manual/data_types.html|title=Data Types, Erlang Reference Manual User's Guide Version 5.10.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en}}</ref>. Ссылка создаётся вызовом функции <code>make_ref/0</code> и может повториться через 2<sup>82</sup> вызовов этой функции{{sfn|Чезарини, Томпсон|2012|с=238}}. Ссылки можно сравнивать на равенство, а применяются они для одноразовых пометок или [[magic cookie|«волшебного печенья»]]{{sfn|Martin Logan, et al|2011|p=36}}.
В языке Erlang имеются и другие типы данных. Тип ''ссылка'' ({{lang-en|reference}}) является практически уникальной в среде времени выполнения Erlang<ref name="datatypes">{{cite web|url=http://www.erlang.org/doc/reference_manual/data_types.html|title=Data Types, Erlang Reference Manual User's Guide Version 5.10.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en|archive-date=2013-12-02|archive-url=https://web.archive.org/web/20131202222450/http://www.erlang.org/doc/reference_manual/data_types.html|deadlink=no}}</ref>. Ссылка создаётся вызовом функции <code>make_ref/0</code> и может повториться через 2<sup>82</sup> вызовов этой функции{{sfn|Чезарини, Томпсон|2012|с=238}}. Ссылки можно сравнивать на равенство, а применяются они для одноразовых пометок или «[[magic cookie|волшебного печенья]]»{{sfn|Martin Logan, et al|2011|p=36}}.


''Идентификатор порта'' ({{lang-en|port identifier}}) определяет порт для связи с внешним по отношению к Erlang-системе миром. Порт позволяет создавшему его процессу-владельцу (так называемому присоединённому процессу) обмениваться бинарными сообщениями со сторонними программами и ОС способом, принятым в данной операционной системе{{sfn|Martin Logan, et al|2011|p=36}}<ref name="ports">{{cite web|url=http://www.erlang.org/doc/reference_manual/ports.html|title=Ports and Port Drivers, Reference Manual User's Guide Version 5.10.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en}}</ref>{{sfn|Чезарини, Томпсон|2012|с=41-42}}.
''Идентификатор порта'' ({{lang-en|port identifier}}) определяет порт для связи с внешним по отношению к Erlang-системе миром. Порт позволяет создавшему его процессу-владельцу (так называемому присоединённому процессу) обмениваться бинарными сообщениями со сторонними программами и ОС способом, принятым в данной операционной системе{{sfn|Martin Logan, et al|2011|p=36}}<ref name="ports">{{cite web|url=http://www.erlang.org/doc/reference_manual/ports.html|title=Ports and Port Drivers, Reference Manual User's Guide Version 5.10.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en|archive-date=2013-12-03|archive-url=https://web.archive.org/web/20131203022736/http://www.erlang.org/doc/reference_manual/ports.html|deadlink=no}}</ref>{{sfn|Чезарини, Томпсон|2012|с=41—42}}.


''Идентификатор процесса'' ({{lang-en|Pid}}), как и следует из его названия, идентифицирует процесс, порождаемый различными функциями <code>spawn</code>. Идентификатор можно считать уникальным во время работы Erlang-системы, но в долго работающих системах могут всё-таки быть использованы повторно, что обычно не является проблемой на практике{{sfn|Martin Logan, et al|2011|p=36}}.
''Идентификатор процесса'' ({{lang-en|Pid}}), как и следует из его названия, идентифицирует процесс, порождаемый различными функциями <code>spawn</code>. Идентификатор можно считать уникальным во время работы Erlang-системы, но в долго работающих системах могут всё-таки быть использованы повторно, что обычно не является проблемой на практике{{sfn|Martin Logan, et al|2011|p=36}}.
Строка 279: Строка 280:
| <code>div</code> || Целочисленное деление || <code>5 div 3</code> || <code>1</code>
| <code>div</code> || Целочисленное деление || <code>5 div 3</code> || <code>1</code>
|-
|-
| <code>rem</code> || Целочисленное [[деление с остатком]]|| <code>5 rem 3</code> || <code>2</code>
| <code>rem</code> || Нахождение [[деление с остатком|остатка от деления]]|| <code>5 rem 3</code> || <code>2</code>
|}
|}
Все эти операции [[ассоциативность (программирование)|левоассоциативны]]. Унарные операции имеют наивысший приоритет, затем следует умножение и деление, наименьший приоритет у сложения и вычитания. При необходимости целое может приводиться к типу с плавающей запятой{{sfn|Чезарини, Томпсон|2012|с=40-41}}.
Все эти операции [[ассоциативность (программирование)|левоассоциативны]]. Унарные операции имеют наивысший приоритет, затем следует умножение и деление, наименьший приоритет у сложения и вычитания. При необходимости целое может приводиться к типу с плавающей запятой{{sfn|Чезарини, Томпсон|2012|с=40—41}}.


==== Битовые операции ====
==== Битовые операции ====
[[Битовая операция|Битовые операции]] работают над целыми числами и дают в результате целое число{{sfn|Чезарини, Томпсон|2012|с=235-236}}.
[[Битовая операция|Битовые операции]] работают над целыми числами и дают в результате целое число{{sfn|Чезарини, Томпсон|2012|с=235—236}}.
{| class="wikitable"
{| class="wikitable"
! Обозначение !! Выполняемая операция !! Пример !! Результат примера
! Обозначение !! Выполняемая операция !! Пример !! Результат примера
Строка 302: Строка 303:


==== Логические операции ====
==== Логические операции ====
[[Логическая операция|Логические операции]] работают над логическими значениями <code>true</code> (истина) и <code>false</code> (ложь), получаемыми в результате сравнений и применения функций проверки типа{{sfn|Чезарини, Томпсон|2012|с=43-44}}.
[[Логическая операция|Логические операции]] работают над логическими значениями <code>true</code> (истина) и <code>false</code> (ложь), получаемыми в результате сравнений и применения функций проверки типа{{sfn|Чезарини, Томпсон|2012|с=43—44}}.
{| class="wikitable"
{| class="wikitable"
! Обозначение !! Выполняемая операция !! Пример !! Результат примера
! Обозначение !! Выполняемая операция !! Пример !! Результат примера
Строка 320: Строка 321:


==== Операции сравнения ====
==== Операции сравнения ====
Операции сравнения получают два операнда, а результатом операции является логическое значение <code>true</code> или <code>false</code>. В Erlang есть следующие операции: <code>==</code> (равно), <code>/=</code> (не равно), <code>=<</code> (меньше или равно), <code><</code> (меньше), <code>></code> (больше), а также сравнения, которые работают без приведения к одному типу: <code>=/=</code> (не равно в точности) и <code>=:=</code> (равно в точности).
Операции сравнения получают два операнда, а результатом операции является логическое значение <code>true</code> или <code>false</code>. В Erlang есть следующие операции: <code>==</code> (равно), <code>/=</code> (не равно), <code>=<</code> (меньше или равно), <code><</code> (меньше), <code>></code> (больше), <code>>=</code> (больше или равно), а также сравнения, которые работают без приведения к одному типу: <code>=/=</code> (не равно в точности) и <code>=:=</code> (равно в точности).


Можно сравнивать и значения разных типов, но они считаются в Erlang упорядоченными следующим образом{{sfn|Чезарини, Томпсон|2012|с=51-52}}:
Можно сравнивать и значения разных типов, но они считаются в Erlang упорядоченными следующим образом{{sfn|Чезарини, Томпсон|2012|с=51—52}}:


: число < атом < ссылка < функция < порт < идентификатор процесса < кортеж < список < бинарные данные
: число < атом < ссылка < функция < порт < идентификатор процесса < кортеж < список < бинарные данные


Списки считаются упорядоченными в [[лексикографический порядок|лексикографическом порядке]], а кортежи сравниваются по длине, и только затем в лексикографическом порядке{{sfn|Чезарини, Томпсон|2012|с=51-52}}.
Списки считаются упорядоченными в [[лексикографический порядок|лексикографическом порядке]], а кортежи сравниваются по длине, и только затем в лексикографическом порядке{{sfn|Чезарини, Томпсон|2012|с=51—52}}.


=== Переменные ===
=== Переменные ===
Переменные служат для хранения значений простых и составных типов. Имя переменной начинается с прописной буквы (в специальных случаях — с подчёркивания) и может содержать буквы, цифры, подчёркивания. Значение можно присвоить переменной лишь один раз — это свойство языка программирования называется единичным присваиванием ({{lang-en|single assignment}}){{sfn|Чезарини, Томпсон|2012|с=53-55}}. К достоинствам единичного присваивания можно отнести устранение необходимости в блокировках, а также упрощение отладки программы{{sfn|Zachary Kessin|2012|p=2-3}}.
Переменные служат для хранения значений простых и составных типов. Имя переменной начинается с прописной буквы (в специальных случаях — с подчёркивания) и может содержать буквы, цифры, подчёркивания. Значение можно присвоить переменной лишь один раз — это свойство языка программирования называется единичным присваиванием ({{lang-en|single assignment}}){{sfn|Чезарини, Томпсон|2012|с=53—55}}. К достоинствам единичного присваивания можно отнести устранение необходимости в блокировках, а также упрощение отладки программы{{sfn|Zachary Kessin|2012|p=2—3}}.


Передача параметров в функцию происходит [[параметр (программирование)#Передача параметра по значению|по значению]], поэтому все они вычисляются перед вызовом функции{{sfn|Чезарини, Томпсон|2012|с=53-55}}.
Передача параметров в функцию происходит [[параметр (программирование)#Передача параметра по значению|по значению]], поэтому все они вычисляются перед вызовом функции{{sfn|Чезарини, Томпсон|2012|с=53—55}}.


[[Область видимости]] переменной распространяется от момента её появления в заголовочной части описания функции или присваивания до конца части описания функции. Пример{{sfn|Чезарини, Томпсон|2012|с=74}}:
[[Область видимости]] переменной распространяется от момента её появления в заголовочной части описания функции или присваивания до конца части описания функции. Пример{{sfn|Чезарини, Томпсон|2012|с=74}}:
Строка 347: Строка 348:


=== Сопоставление с образцом ===
=== Сопоставление с образцом ===
Сопоставление с образцом используется в Erlang для [[присваивание|присваивания]] (в том числе, при работе с параметрами функций), управления потоком выполнения программы, извлечения значений составных типов, выбора сообщения из очереди. В левой части сравнения (или в заголовке функции) могут находиться связанные (уже имеющие значение) и несвязанные (получающие значение) переменные, а также литералы (атомы, числа, строки). В результате исполнения сравнение может оказаться успешным (в этом случае переменные связываются со значениями) и неуспешным — переменные остаются несвязанными. В образце могут быть переменные, значение которых для образца безразлично: их имена записываются начинающимися с подчёркивания{{sfn|Чезарини, Томпсон|2012|с=57-62}}. Переменная с именем <code>_</code> (подчёркивание) сопоставляется с любым значением, но при этом не происходит связывания. Такую переменную можно применять много раз.
Сопоставление с образцом используется в Erlang для [[присваивание|присваивания]] (в том числе, при работе с параметрами функций), управления потоком выполнения программы, извлечения значений составных типов, выбора сообщения из очереди. В левой части сравнения (или в заголовке функции) могут находиться связанные (уже имеющие значение) и несвязанные (получающие значение) переменные, а также литералы (атомы, числа, строки). В результате исполнения сравнение может оказаться успешным (в этом случае переменные связываются со значениями) и неуспешным — переменные остаются несвязанными. В образце могут быть переменные, значение которых для образца безразлично: их имена записываются начинающимися с подчёркивания{{sfn|Чезарини, Томпсон|2012|с=57—62}}. Переменная с именем <code>_</code> (подчёркивание) сопоставляется с любым значением, но при этом не происходит связывания. Такую переменную можно применять много раз.


=== Функции ===
=== Функции ===
Программы на Erlang состоят из функций, которые вызывают друг друга. Количество параметров функции называется '''''арностью'''''. При вызове функции заголовочные части описания функции сопоставляются с образцом. В случае совпадения параметров вызова, формальные параметры связываются с фактическими и исполняется соответствующая часть тела функции{{sfn|Чезарини, Томпсон|2012|с=62-65}}. Запись варианта вычисления функции для некоторого образца может называется ''клозом'' от {{lang-en|clause}}, а определение функции — это набор из одного или более клозов<ref>{{книга|автор=Душкин Р.|заглавие=Функциональное программирование на языке Haskell|издательство=ДМК-Пресс|год=2007|isbn=5-94074-335-8|страниц=608|ref=Душкин|страницы=120}}</ref>.
Программы на Erlang состоят из функций, которые вызывают друг друга. Количество параметров функции называется '''''арностью'''''. При вызове функции заголовочные части описания функции сопоставляются с образцом. В случае совпадения параметров вызова, формальные параметры связываются с фактическими и исполняется соответствующая часть тела функции{{sfn|Чезарини, Томпсон|2012|с=62—65}}. Запись варианта вычисления функции для некоторого образца может называется ''клозом'' от {{lang-en|clause}}, а определение функции — это набор из одного или более клозов<ref>{{книга|автор=Душкин Р.|заглавие=Функциональное программирование на языке Haskell|издательство=ДМК-Пресс|год=2007|isbn=5-94074-335-8|страниц=608|ref=Душкин|страницы=120}}</ref>.


Для уточнения сопоставления с образцов в функциях можно использовать [[охрана (программирование)|охранные выражения]], которые следуют после ключевого слова <code>when</code>{{sfn|Simon St. Laurent|2013|с=30-31}}. В примере ниже определена функция вычисления [[Sgn|знака числа]], которая рассчитывается в зависимости от сравнения параметра с нулём:
Для уточнения сопоставления с образцом в функциях можно использовать [[охрана (программирование)|охранные выражения]], которые следуют после ключевого слова <code>when</code>{{sfn|Simon St. Laurent|2013|с=30—31}}. В примере ниже определена функция вычисления [[Sgn|знака числа]], которая рассчитывается в зависимости от сравнения параметра с нулём:


<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
Строка 375: Строка 376:
4> (Plus(2))(3). % Дополнительные скобки позволяют добиться требуемого результата
4> (Plus(2))(3). % Дополнительные скобки позволяют добиться требуемого результата
5
5
5> Plus2 = Plus(2), Plus2(3). % То же самое с использование дополнительной переменной
5> Plus2 = Plus(2), Plus2(3). % То же самое с использованием дополнительной переменной
5
5
</syntaxhighlight>
</syntaxhighlight>
Строка 415: Строка 416:
end
end
</syntaxhighlight>
</syntaxhighlight>
Это выражение всегда возвращает значение, соответствующее последнему вычисленному выражению в строке с подошедшим образцом. Это возвращаемое значение может служить возвращаемым значением функции, а может быть присвоено переменной{{sfn|Чезарини, Томпсон|2012|с=71-73}}. Как и в заголовочной части функции, после образца может следовать охранное выражение.
Это выражение всегда возвращает значение, соответствующее последнему вычисленному выражению в строке с подошедшим образцом. Это возвращаемое значение может служить возвращаемым значением функции, а может быть присвоено переменной{{sfn|Чезарини, Томпсон|2012|с=71—73}}. Как и в заголовочной части функции, после образца может следовать охранное выражение.


Упрощённым вариантом case-выражения является if-выражение:
Упрощённым вариантом case-выражения является if-выражение:
Строка 427: Строка 428:
</syntaxhighlight>
</syntaxhighlight>


Здесь <code>охранаi</code> — охранное выражение. Первое истинное охранное выражение вызывает выполнение соответствующих выражений, последнее из которых и является значением всего if-выражение{{sfn|Чезарини, Томпсон|2012|с=75-76}}. Следует заметить, что и здесь в охранном выражении можно применять только ограниченный набор операций и встроенных функций.
Здесь <code>охранаi</code> — охранное выражение. Первое истинное охранное выражение вызывает выполнение соответствующих выражений, последнее из которых и является значением всего if-выражение{{sfn|Чезарини, Томпсон|2012|с=75—76}}. Следует заметить, что и здесь в охранном выражении можно применять только ограниченный набор операций и встроенных функций.


Запятые в охранном выражении работают как операция <code>and</code>, например{{sfn|Simon St. Laurent|2013|с=42}}:
Запятые в охранном выражении работают как операция <code>and</code>, например{{sfn|Simon St. Laurent|2013|с=42}}:
Строка 461: Строка 462:
</syntaxhighlight>
</syntaxhighlight>


Правильным было бы определить все используемые далее по коду переменные во всех ветвях if-выражения{{sfn|Simon St. Laurent|2013|с=44-45}}.
Правильным было бы определить все используемые далее по коду переменные во всех ветвях if-выражения{{sfn|Simon St. Laurent|2013|с=44—45}}.


=== Препроцессор и макросы ===
=== Препроцессор и макросы ===
Строка 471: Строка 472:
</syntaxhighlight>
</syntaxhighlight>


Имя макроса обычно пишется прописными буквами. Определение макроса должно содержать [[лексема (информатика)|лексемы]] Erlang целиком (например, попытка задать часть имени переменной с помощью макроса вызовет синтаксическую ошибку). Макросы могут использоваться для повышения [[удобочитаемость|удобочитаемости]] кода в охранных выражениях, для операторов отладки и т. п.{{sfn|Чезарини, Томпсон|2012|с=194-195}} Препроцессор имеет несколько предопределённых макросов, которые нельзя переопределить: <code>?MODULE</code>, <code>?MODULE_STRING</code>, <code>?FILE</code>, <code>?LINE</code>, <code>?MACHINE</code><ref>{{cite web|url=http://www.erlang.org/doc/reference_manual/macros.html|title=The Preprocessor, Predefined Macros, Erlang Reference Manual User's Guide Version 5.10.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en}}</ref>.
Имя макроса обычно пишется прописными буквами. Определение макроса должно содержать [[лексема (информатика)|лексемы]] Erlang целиком (например, попытка задать часть имени переменной с помощью макроса вызовет синтаксическую ошибку). Макросы могут использоваться для повышения [[удобочитаемость|удобочитаемости]] кода в охранных выражениях, для операторов отладки и т. п.{{sfn|Чезарини, Томпсон|2012|с=194—195}} Препроцессор имеет несколько предопределённых макросов, которые нельзя переопределить: <code>?MODULE</code>, <code>?MODULE_STRING</code>, <code>?FILE</code>, <code>?LINE</code>, <code>?MACHINE</code><ref>{{cite web|url=http://www.erlang.org/doc/reference_manual/macros.html|title=The Preprocessor, Predefined Macros, Erlang Reference Manual User's Guide Version 5.10.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en|archive-date=2013-12-02|archive-url=https://web.archive.org/web/20131202235554/http://www.erlang.org/doc/reference_manual/macros.html|deadlink=no}}</ref>.


Заголовочный файл (расширение <code>.hrl</code>) с определениями макросов и записей можно включить при помощи директивы <code>-include</code>{{sfn|Чезарини, Томпсон|2012|с=196-197}}.
Заголовочный файл (расширение <code>.hrl</code>) с определениями макросов и записей можно включить при помощи директивы <code>-include</code>{{sfn|Чезарини, Томпсон|2012|с=196—197}}.


=== Обработка ошибок ===
=== Обработка ошибок ===
Строка 491: Строка 492:
</syntaxhighlight>
</syntaxhighlight>


Как и в случае case-выражения, вычисляемое выражение сопоставляется с образцом (части между <code>of</code> и <code>catch</code>) для получения результата<ref group="Примечание">Вариант с <code>of</code> употребляется редко</ref>{{sfn|Simon St. Laurent|2013|с=108}}. После ключевого слова <code>catch</code> следуют части обработки исключений, в которых в дополнение к образцам исключений могут быть указаны классы исключений (перед двоеточием): <code>error</code>, <code>throw</code> и <code>exit</code>. Подчёркивание может использоваться как в образце, так и в классе исключения{{sfn|Чезарини, Томпсон|2012|с=98-102}}. Следующий простой пример иллюстрирует перехват ошибки класса <code>error</code> при вычислении [[квадратный корень|квадратного корня]]:
Как и в случае case-выражения, вычисляемое выражение сопоставляется с образцом (части между <code>of</code> и <code>catch</code>) для получения результата<ref group="Примечание">Вариант с <code>of</code> употребляется редко.</ref>{{sfn|Simon St. Laurent|2013|с=108}}. После ключевого слова <code>catch</code> следуют части обработки исключений, в которых в дополнение к образцам исключений могут быть указаны классы исключений (перед двоеточием): <code>error</code>, <code>throw</code> и <code>exit</code>. Подчёркивание может использоваться как в образце, так и в классе исключения{{sfn|Чезарини, Томпсон|2012|с=98—102}}. Следующий простой пример иллюстрирует перехват ошибки класса <code>error</code> при вычислении [[квадратный корень|квадратного корня]]:
<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
1> try math:sqrt(-1) catch error:Error -> {error, Error} end.
1> try math:sqrt(-1) catch error:Error -> {error, Error} end.
Строка 498: Строка 499:
2.0
2.0
</syntaxhighlight>
</syntaxhighlight>
Для создания исключений, определённых пользователем, используется функция <code>throw/1</code>, которая принимает кортеж с более детальным описанием возникшей ошибки{{sfn|Simon St. Laurent|2013|с=110}} и генерирует исключение класса <code>throw</code>. Использование этой функции нежелательно из-за ухудшения удобочитаемости кода программы, но может потребоваться в некоторых случаях при работе с вложенными структурами данных, например, при разборе [[XML]]{{sfn|Чезарини, Томпсон|2012|с=98-102}}. Исключения класса <code>exit</code> возникают в результате вызова встроенной функции <code>exit/1</code> или сигнала выхода{{sfn|Чезарини, Томпсон|2012|с=98-102}}.
Для создания исключений, определённых пользователем, используется функция <code>throw/1</code>, которая принимает кортеж с более детальным описанием возникшей ошибки{{sfn|Simon St. Laurent|2013|с=110}} и генерирует исключение класса <code>throw</code>. Использование этой функции нежелательно из-за ухудшения удобочитаемости кода программы, но может потребоваться в некоторых случаях при работе с вложенными структурами данных, например, при разборе [[XML]]{{sfn|Чезарини, Томпсон|2012|с=98—102}}. Исключения класса <code>exit</code> возникают в результате вызова встроенной функции <code>exit/1</code> или сигнала выхода{{sfn|Чезарини, Томпсон|2012|с=98—102}}.


До разработки Ричардом Карлссоном (Richard Carlsson) из команды проекта HiPE описанного выше нового механизма обработки исключений (появился в версии R10B) в Erlang использовались catch-выражения{{sfn|Чезарини, Томпсон|2012|с=102}}.
До разработки Ричардом Карлссоном (Richard Carlsson) из команды проекта HiPE описанного выше нового механизма обработки исключений (появился в версии R10B) в Erlang использовались catch-выражения{{sfn|Чезарини, Томпсон|2012|с=102}}.


=== Модули ===
=== Модули ===
Код программы на Erlang можно разбить на отдельные [[модуль (программирование)|модули]]. Модуль — имя для набора функций, организованных в одном файле. Имя модуля должно совпадать с именем файла (если отбросить [[расширение имени файла|расширение]]){{sfn|Чезарини, Томпсон|2012|с=65-66}}. Модуль можно откомпилировать в байт-код как из командной строки операционной системы, так и из командной оболочки Erlang{{sfn|Hebert|2013|loc=Modules}}. В файле модуля можно записать объявления функций и '''''директивы''''' (иногда называются атрибутами){{sfn|Simon St. Laurent|2013|с=18}}. Обязательным атрибутом является только <code>-module(атом_имени_модуля).</code> Другой часто используемый атрибут — <code>-export</code> — применяется для указания списка экспортируемых функций, то есть функций, которые можно использовать за пределами модуля.
Код программы на Erlang можно разбить на отдельные [[модуль (программирование)|модули]]. Модуль — имя для набора функций, организованных в одном файле. Имя модуля должно совпадать с именем файла (если отбросить [[расширение имени файла|расширение]]){{sfn|Чезарини, Томпсон|2012|с=65—66}}. Модуль можно откомпилировать в байт-код как из командной строки операционной системы, так и из командной оболочки Erlang{{sfn|Hebert|2013|loc=Modules}}. В файле модуля можно записать объявления функций и '''''директивы''''' (иногда называются атрибутами){{sfn|Simon St. Laurent|2013|с=18}}. Обязательным атрибутом является только <code>-module(атом_имени_модуля).</code> Другой часто используемый атрибут — <code>-export</code> — применяется для указания списка экспортируемых функций, то есть функций, которые можно использовать за пределами модуля.


Функции в Erlang однозначно определяются модулем, именем и [[арность]]ю. Например, <code>math:cos/1</code> соответствует функции <code>cos</code> из модуля <code>math</code>, принимающей один аргумент. Вызвать функцию можно так: <code>math:cos(1.2)</code>{{sfn|Чезарини, Томпсон|2012|с=65-66}}.
Функции в Erlang однозначно определяются модулем, именем и [[арность]]ю. Например, <code>math:cos/1</code> соответствует функции <code>cos</code> из модуля <code>math</code>, принимающей один аргумент. Вызвать функцию можно так: <code>math:cos(1.2)</code>{{sfn|Чезарини, Томпсон|2012|с=65—66}}.


[[Исходный код|Исходный текст]] модуля компилируется в BEAM-файл — файл, содержащий байт-код виртуальной машины '''''BEAM''''' ({{lang-en|Bogdan’s/Björn's Erlang Abstract Machine}}{{sfn|Hebert|2013|loc=Modules}}). В свою очередь, '''''ERTS''''' ({{lang-en|Erlang Runtime System}} — система времени выполнения Erlang) выполняет этот код{{sfn|Simon St. Laurent|2013|с=17}}.
[[Исходный код|Исходный текст]] модуля компилируется в BEAM-файл — файл, содержащий байт-код виртуальной машины '''''BEAM''''' ({{lang-en|Bogdan’s/Björn's Erlang Abstract Machine}}{{sfn|Hebert|2013|loc=Modules}}). В свою очередь, '''''ERTS''''' ({{lang-en|Erlang Runtime System}} — система времени выполнения Erlang) выполняет этот код{{sfn|Simon St. Laurent|2013|с=17}}.
Строка 513: Строка 514:


==== Создание процессов ====
==== Создание процессов ====
Для создания нового процесса служит несколько встроенных функций (<code>spawn</code> и её аналоги){{sfn|Martin Logan, et al|2011|p=75}}. Функции возвращают идентификатор процесса, который может использоваться, например, для отправки сообщений вновь созданному процессу. В интерактивной консоли erl можно получить список процессов и другую информацию посредством вызова функций <code>processes().</code> и <code>i().</code> соответственно{{sfn|Чезарини, Томпсон|2012|с=120-124}}.
Для создания нового процесса служит несколько встроенных функций (<code>spawn</code> и её аналоги){{sfn|Martin Logan, et al|2011|p=75}}. Функции возвращают идентификатор процесса, который может использоваться, например, для отправки сообщений вновь созданному процессу. В интерактивной консоли erl можно получить список процессов и другую информацию посредством вызова функций <code>processes().</code> и <code>i().</code> соответственно{{sfn|Чезарини, Томпсон|2012|с=120—124}}.


==== Отправка и приём сообщений ====
==== Отправка и приём сообщений ====
Как и язык [[Occam|Оккам]], Erlang использует для отправки сообщения синтаксис с восклицательным знаком: <code>ИдПроцесса ! Сообщение</code>. Приём сообщения — то есть извлечение его из очереди («почтового ящика») процесса — выполняется с помощью receive-выражений, обычно записываемых следующим образом{{sfn|Чезарини, Томпсон|2012|с=118-120}}:
Как и язык [[Occam|Оккам]], Erlang использует для отправки сообщения синтаксис с восклицательным знаком: <code>ИдПроцесса ! Сообщение</code>. Приём сообщения — то есть извлечение его из очереди («почтового ящика») процесса — выполняется с помощью receive-выражений, обычно записываемых следующим образом{{sfn|Чезарини, Томпсон|2012|с=118—120}}:
<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
receive
receive
Строка 527: Строка 528:
</syntaxhighlight>
</syntaxhighlight>


Встретив такое выражение, интерпретатор последовательно просматривает сообщения из очереди. Каждое сообщение интерпретатор сопоставляет с образцом и, если оно удовлетворяет образцу, вычисляются соответствующие выражения. Когда все сообщения перебраны, и подходящего не оказалось, процесс блокируется в ожидании новых сообщений, после чего перебор очереди повторяется. Если в receive-выражении отсутствует образец, которому удовлетворяет любое сообщение, такое выражение называется выборочным receive-выражением{{sfn|Чезарини, Томпсон|2012|с=120-124}}.
Встретив такое выражение, интерпретатор последовательно просматривает сообщения из очереди. Каждое сообщение интерпретатор сопоставляет с образцом и, если оно удовлетворяет образцу, вычисляются соответствующие выражения. Когда все сообщения перебраны, и подходящего не оказалось, процесс блокируется в ожидании новых сообщений, после чего перебор очереди повторяется. Если в receive-выражении отсутствует образец, которому удовлетворяет любое сообщение, такое выражение называется выборочным receive-выражением{{sfn|Чезарини, Томпсон|2012|с=120—124}}.


==== Обработка ошибок и завершение процессов ====
==== Обработка ошибок и завершение процессов ====
Процесс можно связать с другим, в результате чего между процессами устанавливается ''двунаправленное соединение'' ({{lang-en|link}}). В случае, если один из процессов завершается ненормально, всем связанным с ним процессам передаётся ''сигнал выхода'' ({{lang-en|exit signal}}). Процессы, получившие сигнал, завершаются, распространяя сигнал дальше{{sfn|Чезарини, Томпсон|2012|с=167-168}}{{sfn|Cesarini, Thompson|2009|p=139}}<!-- в русском переводе проблемы -->. Сигнал выхода является кортежем, элементами которого являются атом <code>'EXIT'</code> (выход), идентификатор завершившегося процесса и причину завершения процесса. Причина завершения передаётся по цепочке завершающихся процессов{{sfn|Чезарини, Томпсон|2012|с=168-169}}.
Процесс можно связать с другим, в результате чего между процессами устанавливается ''двунаправленное соединение'' ({{lang-en|link}}). В случае, если один из процессов завершается ненормально, всем связанным с ним процессам передаётся ''сигнал выхода'' ({{lang-en|exit signal}}). Процессы, получившие сигнал, завершаются, распространяя сигнал дальше{{sfn|Чезарини, Томпсон|2012|с=167—168}}{{sfn|Cesarini, Thompson|2009|p=139}}<!-- в русском переводе проблемы -->. Сигнал выхода является кортежем, элементами которого являются атом <code>'EXIT'</code> (выход), идентификатор завершившегося процесса и причину завершения процесса. Причина завершения передаётся по цепочке завершающихся процессов{{sfn|Чезарини, Томпсон|2012|с=168—169}}.


Процесс может осуществить ''перехват ошибки'' ({{lang-en|trapping errors}}), если у него установлен флаг перехвата выхода<ref group="Примечание">Флаг <code>trap_exit</code> можно установить с помощью функции <code>process_flag/2</code></ref>. Такой процесс получает сигналы выхода связанных с ним процессов в виде обычных сообщений с той же структурой кортежа. Перехваченный сигнала выхода более не передаётся связанным с процессом-перехватчиком процессам{{sfn|Чезарини, Томпсон|2012|с=170-171,175}}. Сигнал выхода с причиной — атомом <code>normal</code> (нормальное завершение процесса) не вызывает завершения связанного процесса. Если же причина — атом <code>kill</code>, процесс завершается безусловно (независимо от флага перехвата выхода), а связанным с ним процессам в качестве причины отправляется атом <code>killed</code>, что даёт им возможность среагировать{{sfn|Чезарини, Томпсон|2012|с=176-177}}.
Процесс может осуществить ''перехват ошибки'' ({{lang-en|trapping errors}}), если у него установлен флаг перехвата выхода<ref group="Примечание">Флаг <code>trap_exit</code> можно установить с помощью функции <code>process_flag/2</code>.</ref>. Такой процесс получает сигналы выхода связанных с ним процессов в виде обычных сообщений с той же структурой кортежа. Перехваченный сигнала выхода более не передаётся связанным с процессом-перехватчиком процессам{{sfn|Чезарини, Томпсон|2012|с=170—171, 175}}. Сигнал выхода с причиной — атомом <code>normal</code> (нормальное завершение процесса) не вызывает завершения связанного процесса. Если же причина — атом <code>kill</code>, процесс завершается безусловно (независимо от флага перехвата выхода), а связанным с ним процессам в качестве причины отправляется атом <code>killed</code>, что даёт им возможность среагировать{{sfn|Чезарини, Томпсон|2012|с=176—177}}.


В Erlang есть возможность установить и однонаправленное соединение. При завершении наблюдаемого процесса процесс-наблюдатель получает сообщение с указанием причины завершения{{sfn|Чезарини, Томпсон|2012|с=172-174}}.
В Erlang есть возможность установить и однонаправленное соединение. При завершении наблюдаемого процесса процесс-наблюдатель получает сообщение с указанием причины завершения{{sfn|Чезарини, Томпсон|2012|с=172—174}}.


Процесс может остановить сам себя или другой процесс, вызвав функцию <code>exit</code>{{sfn|Чезарини, Томпсон|2012|с=174}}.
Процесс может остановить сам себя или другой процесс, вызвав функцию <code>exit</code>{{sfn|Чезарини, Томпсон|2012|с=174}}.
Строка 541: Строка 542:
В [[планировщик задач|планировщике]] процессов Erlang-системы проблема [[ввод-вывод|ввода-вывода]], присущая многим другим языкам параллельного программирования, решена достаточно элегантно. Управление вводом-выводом, интегрированное с планировщиком, уже на самом нижнем уровне осуществляется на основе событий, что позволяет программе обрабатывать входящие и исходящие данные без излишних блокировок. Такой подход требует меньшего числа установки и разрыва соединений, а также убирает необходимость в блокировках и [[переключение контекста|переключениях контекста]]. К сожалению, такой достаточно эффективный способ более сложен для понимания программистами, и находит применение в основном в системах с явными требования по высокой доступности и низкому времени отклика. Реализация событийно-ориентированного ввода-вывода встроена в Erlang-систему, что является ещё одним преимуществом при проектировании параллельных приложений{{sfn|Martin Logan, et al|2011|p=19}}.
В [[планировщик задач|планировщике]] процессов Erlang-системы проблема [[ввод-вывод|ввода-вывода]], присущая многим другим языкам параллельного программирования, решена достаточно элегантно. Управление вводом-выводом, интегрированное с планировщиком, уже на самом нижнем уровне осуществляется на основе событий, что позволяет программе обрабатывать входящие и исходящие данные без излишних блокировок. Такой подход требует меньшего числа установки и разрыва соединений, а также убирает необходимость в блокировках и [[переключение контекста|переключениях контекста]]. К сожалению, такой достаточно эффективный способ более сложен для понимания программистами, и находит применение в основном в системах с явными требования по высокой доступности и низкому времени отклика. Реализация событийно-ориентированного ввода-вывода встроена в Erlang-систему, что является ещё одним преимуществом при проектировании параллельных приложений{{sfn|Martin Logan, et al|2011|p=19}}.


Стандартная библиотека содержит модуль <code>io</code> с функциями ввода-вывода. Такие функции содержат [[побочный эффект (программирование)|побочные эффекты]], заключающиеся в появлении выведенной информации на консоли или записывании данных в файл на диске. Например, функция <code>io:format</code> для форматированного вывода выводит строку с подстановкой параметров, возвращая в случае успеха атом <code>ok</code>{{sfn|Чезарини, Томпсон|2012|с=83-84}}:
Стандартная библиотека содержит модуль <code>io</code> с функциями ввода-вывода. Такие функции содержат [[побочный эффект (программирование)|побочные эффекты]], заключающиеся в появлении выведенной информации на консоли или записывании данных в файл на диске. Например, функция <code>io:format</code> для форматированного вывода выводит строку с подстановкой параметров, возвращая в случае успеха атом <code>ok</code>{{sfn|Чезарини, Томпсон|2012|с=83—84}}:


<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="Erlang">
Строка 549: Строка 550:
</syntaxhighlight>
</syntaxhighlight>


Функции модуля <code>io</code> включают в себя стандартный серверный интерфейс ввода-вывода. Протокол ввода-вывода Erlang ({{lang-en|The Erlang I/O-protocol}}) детально определяет связь клиента и сервера. Под сервером ввода-вывода понимается процесс, который обрабатывает запросы и выполняет запрошенные команды, например, на устройстве ввода-вывода. Клиентом является любой Erlang-процесс, которому требуется работать с устройством<ref>{{cite web|url=http://erlang.org/doc/apps/stdlib/io_protocol.html|title=The Erlang I/O-protocol, STDLIB User's Guide Version 1.19.4|date=2013|publisher=Ericsson AB|accessdate=2013-12-21|lang=en}}</ref>{{sfn|Cesarini, Thompson|2009|p=79}}<!-- в рус. изд. суть потеряна -->.
Функции модуля <code>io</code> включают в себя стандартный серверный интерфейс ввода-вывода. Протокол ввода-вывода Erlang ({{lang-en|The Erlang I/O-protocol}}) детально определяет связь клиента и сервера. Под сервером ввода-вывода понимается процесс, который обрабатывает запросы и выполняет запрошенные команды, например, на устройстве ввода-вывода. Клиентом является любой Erlang-процесс, которому требуется работать с устройством<ref>{{cite web|url=http://erlang.org/doc/apps/stdlib/io_protocol.html|title=The Erlang I/O-protocol, STDLIB User's Guide Version 1.19.4|date=2013|publisher=Ericsson AB|accessdate=2013-12-21|lang=en|archive-date=2013-12-24|archive-url=https://web.archive.org/web/20131224105137/http://erlang.org/doc/apps/stdlib/io_protocol.html|deadlink=no}}</ref>{{sfn|Cesarini, Thompson|2009|p=79}}<!-- в рус. изд. суть потеряна -->.


== Библиотеки ==
== Библиотеки ==


=== Стандартная библиотека модулей ===
=== Стандартная библиотека модулей ===
Согласно официальной документации, стандартная библиотека модулей STDLIB<ref>{{cite web|url=http://www.erlang.org/doc/apps/stdlib/|title=STDLIB Reference Manual Version 1.19.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en}}</ref> является обязательной для включения в минимальную систему Erlang/OTP<ref>{{cite web|url=http://www.erlang.org/doc/man/STDLIB_app.html|title=STDLIB, STDLIB Reference Manual Version 1.19.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en}}</ref> наряду с ядром Erlang. В библиотеку входят модули, предоставляющие разнообразные функции для работы со встроенными типами и другими структурами данных, ввода-вывода, обращения к среде окружения, для работы с файловой системой, процессами и т. п.
Согласно официальной документации, стандартная библиотека модулей STDLIB<ref>{{cite web|url=http://www.erlang.org/doc/apps/stdlib/|title=STDLIB Reference Manual Version 1.19.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en|archive-date=2013-12-03|archive-url=https://web.archive.org/web/20131203003936/http://www.erlang.org/doc/apps/stdlib/|deadlink=no}}</ref> является обязательной для включения в минимальную систему Erlang/OTP<ref>{{cite web|url=http://www.erlang.org/doc/man/STDLIB_app.html|title=STDLIB, STDLIB Reference Manual Version 1.19.3|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en|archive-date=2013-11-07|archive-url=https://web.archive.org/web/20131107140904/http://www.erlang.org/doc/man/STDLIB_app.html|deadlink=no}}</ref> наряду с ядром Erlang. В библиотеку входят модули, предоставляющие разнообразные функции для работы со встроенными типами и другими структурами данных, ввода-вывода, обращения к среде окружения, для работы с файловой системой, процессами и т. п.


Модуль <code>array</code> определяет (функциональный) [[абстрактный тип данных]] для [[динамический массив|динамического массива]] и имеет функции, позволяющие извлекать и обновлять элементы массива, определять рекурсивные функции для работы с массивами. Модуль <code>string</code> расширяет возможности модуля <code>lists</code> функциями для работы конкретно со списками символов, какими являются строки в Erlang. Модуль <code>dict</code> (от {{lang-en|dictionary}} — словарь) содержит функции для [[ассоциативный массив|ассоциативного массива]], позволяющие хранить, извлекать и удалять значения по ключу, соединять массивы и производить итерации по элементам. Математические функции можно найти в модуле <code>math</code>, а функции для [[генератор псевдослучайных чисел|генерации псевдослучайных чисел]] содержатся в модуле <code>random</code>. Модуль <code>calendar</code> предоставляет функции для [[Григорианский календарь|григорианского календаря]]: запросы текущей даты, преобразования единиц измерения и интервалов времени, а модуль <code>timer</code> содержит функции перевода интервалов времени к [[миллисекунда]]м, запуска событий по таймеру и другие, связанные со временем, функции. Модуль <code>erlang</code> содержит все встроенные функции Erlang, как общие, так и относящиеся к виртуальной машине. Модуль <code>file</code> даёт доступ к функциям [[файловая система|файловой системы]], таким как открытие, чтение, запись, удаление [[файл]]ов, а модуль <code>filename</code> позволяет писать функции для манипуляции с именами и [[путь к файлу|путями к файлам]], абстрагируясь от конкретной операционной системы. Модуль <code>io</code> предоставляет функции ввода-вывода. Кроме этих наиболее важных модулей, стандартная библиотека содержит и многие другие, с которыми можно познакомиться по документации{{sfn|Чезарини, Томпсон|2012|с=107-108}}.
Модуль <code>array</code> определяет (функциональный) [[абстрактный тип данных]] для [[динамический массив|динамического массива]] и имеет функции, позволяющие извлекать и обновлять элементы массива, определять рекурсивные функции для работы с массивами. Модуль <code>string</code> расширяет возможности модуля <code>lists</code> функциями для работы конкретно со списками символов, какими являются строки в Erlang. Модуль <code>dict</code> (от {{lang-en|dictionary}} — словарь) содержит функции для [[ассоциативный массив|ассоциативного массива]], позволяющие хранить, извлекать и удалять значения по ключу, соединять массивы и производить итерации по элементам. Математические функции можно найти в модуле <code>math</code>, а функции для [[генератор псевдослучайных чисел|генерации псевдослучайных чисел]] содержатся в модуле <code>random</code>. Модуль <code>calendar</code> предоставляет функции для [[Григорианский календарь|григорианского календаря]]: запросы текущей даты, преобразования единиц измерения и интервалов времени, а модуль <code>timer</code> содержит функции перевода интервалов времени к [[миллисекунда]]м, запуска событий по таймеру и другие, связанные со временем, функции. Модуль <code>erlang</code> содержит все встроенные функции Erlang, как общие, так и относящиеся к виртуальной машине. Модуль <code>file</code> даёт доступ к функциям [[файловая система|файловой системы]], таким как открытие, чтение, запись, удаление [[файл]]ов, а модуль <code>filename</code> позволяет писать функции для манипуляции с именами и [[путь к файлу|путями к файлам]], абстрагируясь от конкретной операционной системы. Модуль <code>io</code> предоставляет функции ввода-вывода. Кроме этих наиболее важных модулей, стандартная библиотека содержит и многие другие, с которыми можно познакомиться по документации{{sfn|Чезарини, Томпсон|2012|с=107—108}}.


==== Таблицы ETS и DETS ====
==== Таблицы ETS и DETS ====
Для организации [[Коллекция (программирование)|коллекций]] в оперативной памяти Erlang предлагает модуль ets (ETS, {{lang-en|Erlang Term Storage}} — «хранилище термов Erlang»<ref group="Примечание">Правильно сформированная [[структура данных]] любого типа называется термом.</ref>). ETS может хранить четыре вида коллекций: [[множество (тип данных)|множество]] ({{lang-en|set}}), [[упорядоченное множество (тип данных)|упорядоченное множество]] ({{lang-en|ordered set}}), [[мультимножество]] ({{lang-en|bag}}), мультимножество с повторениями ({{lang-en|duplicate bag}}){{sfn|Simon St. Laurent|2013|с=131}}. Доступ к элементам коллекций происходит по ключевому полю кортежа (ключи могут быть любых типов). Упорядоченные множества реализованы в виде бинарных сбалансированных [[АВЛ-дерево|АВЛ-деревьев]], а остальные коллекции — с использованием [[хэш-таблица|хэш-таблиц]]{{sfn|Чезарини, Томпсон|2012|с=241-247}}.
Для организации [[Коллекция (программирование)|коллекций]] в оперативной памяти Erlang предлагает модуль ets (ETS, {{lang-en|Erlang Term Storage}} — «хранилище термов Erlang»<ref group="Примечание">Правильно сформированная [[структура данных]] любого типа называется термом.</ref>). ETS может хранить четыре вида коллекций: [[множество (тип данных)|множество]] ({{lang-en|set}}), [[упорядоченное множество (тип данных)|упорядоченное множество]] ({{lang-en|ordered set}}), [[мультимножество]] ({{lang-en|bag}}), мультимножество с повторениями ({{lang-en|duplicate bag}}){{sfn|Simon St. Laurent|2013|с=131}}. Доступ к элементам коллекций происходит по ключевому полю кортежа (ключи могут быть любых типов). Упорядоченные множества реализованы в виде бинарных сбалансированных [[АВЛ-дерево|АВЛ-деревьев]], а остальные коллекции — с использованием [[хеш-таблица|хеш-таблиц]]{{sfn|Чезарини, Томпсон|2012|с=241—247}}.


DETS-таблицы дополняют функциональность ETS-таблиц (за исключением упорядоченных множеств), позволяя сохранять данные в файлах{{sfn|Чезарини, Томпсон|2012|с=257}}.
DETS-таблицы дополняют функциональность ETS-таблиц (за исключением упорядоченных множеств), позволяя сохранять данные в файлах{{sfn|Чезарини, Томпсон|2012|с=257}}.
Строка 568: Строка 569:
OTP ({{lang-en|Open Telecom Platform}}) является хорошо отлаженным набором полезных поведений ({{lang-en|behaviours}}) процессов и используется для создания серверных приложений. OTP формализует действия процессов и позволяет строить на их основе OTP-приложения (не следует путать с приложением — готовым программным продуктом). В модулях ОТР определены общие, стандартизированные шаблоны для конструирования параллельных приложений{{sfn|Чезарини, Томпсон|2012|с=291}}. Наиболее популярными поведениями являются обобщённый сервер и наблюдатель ({{lang-en|supervisor}}), но имеются и другие: [[конечный автомат]], обработчик событий{{sfn|Simon St. Laurent|2013|с=151}}. OTP содержит и другое [[связующее программное обеспечение]] ({{lang-en|middleware}}), например, [[СУБД]] [[Mnesia]].
OTP ({{lang-en|Open Telecom Platform}}) является хорошо отлаженным набором полезных поведений ({{lang-en|behaviours}}) процессов и используется для создания серверных приложений. OTP формализует действия процессов и позволяет строить на их основе OTP-приложения (не следует путать с приложением — готовым программным продуктом). В модулях ОТР определены общие, стандартизированные шаблоны для конструирования параллельных приложений{{sfn|Чезарини, Томпсон|2012|с=291}}. Наиболее популярными поведениями являются обобщённый сервер и наблюдатель ({{lang-en|supervisor}}), но имеются и другие: [[конечный автомат]], обработчик событий{{sfn|Simon St. Laurent|2013|с=151}}. OTP содержит и другое [[связующее программное обеспечение]] ({{lang-en|middleware}}), например, [[СУБД]] [[Mnesia]].


OTP-поведения делятся на рабочие процессы ({{lang-en|worker processes}}), выполняющие собственно обработку запросов, и процессов-наблюдателей ({{lang-en|supervisors}}). В задачу последних входит слежение за рабочими процессами и другими процессами-наблюдателями — потомками. Деревья наблюдателей составляют OTP-приложение ({{lang-en|application}}){{sfn|Чезарини, Томпсон|2012|с=291-294}}. Документация по Erlang определяет OTP-приложение как компонент, реализующий некоторую функциональность, которая может быть независимо запущена на исполнение и остановлена как целое, а также [[повторное использование кода|повторно использована]] в других системах<ref>{{cite web|url=http://www.erlang.org/doc/apps/kernel/application.html|title=application, Kernel Reference Manual Version 2.16.3|date=2013|publisher=Ericsson AB|accessdate=|lang=en}}</ref>. Разработчик приложения пишет код '''''модулей функций обратного вызова''''' ({{lang-en|call-back module}}), в которых и находится специфичная для данного приложения часть функциональности{{sfn|Чезарини, Томпсон|2012|с=291-294}}.
OTP-поведения делятся на рабочие процессы ({{lang-en|worker processes}}), выполняющие собственно обработку запросов, и процессов-наблюдателей ({{lang-en|supervisors}}). В задачу последних входит слежение за рабочими процессами и другими процессами-наблюдателями — потомками. Деревья наблюдателей составляют OTP-приложение ({{lang-en|application}}){{sfn|Чезарини, Томпсон|2012|с=291—294}}. Документация по Erlang определяет OTP-приложение как компонент, реализующий некоторую функциональность, которая может быть независимо запущена на исполнение и остановлена как целое, а также [[повторное использование кода|повторно использована]] в других системах<ref>{{cite web|url=http://www.erlang.org/doc/apps/kernel/application.html|title=application, Kernel Reference Manual Version 2.16.3|date=2013|publisher=Ericsson AB|accessdate=|lang=en|archive-date=2013-11-01|archive-url=https://web.archive.org/web/20131101082248/http://www.erlang.org/doc/apps/kernel/application.html|deadlink=no}}</ref>. Разработчик приложения пишет код '''''модулей функций обратного вызова''''' ({{lang-en|call-back module}}), в которых и находится специфичная для данного приложения часть функциональности{{sfn|Чезарини, Томпсон|2012|с=291—294}}.


Хотя OTP строго говоря не является частью языка Erlang, он настолько вошёл в культуру и практику разработчиков на Erlang, что подчас между ними сложно провести границу{{sfn|Simon St. Laurent|2013|с=151}}.
Хотя OTP строго говоря не является частью языка Erlang, он настолько вошёл в культуру и практику разработчиков на Erlang, что подчас между ними сложно провести границу{{sfn|Simon St. Laurent|2013|с=151}}.


=== Разработка графического интерфейса пользователя ===
=== Разработка графического интерфейса пользователя ===
Разработка приложений с [[GUI|графическим интерфейсом пользователя]] (не считая [[веб-интерфейс]]ов) может вестись при помощи библиотеки wxErlang — библиотеки [[wxWidgets]], портированной для Erlang. WxErlang входит в стандартную поставку Erlang/OTP. WxWidgets написан на [[C++]], поэтому перед разработчиками wxErlang стояла задача выразить средствами Erlang иерархию [[объект (программирование)|объектов]]. Несколько упрощая, в wxErlang [[класс (программирование)|классам]] соответствуют модули, а объектам — ссылки. Макросам на С++ соответствуют макросы Erlang. Некоторые типы данных, для которых в С++ были использованы классы, представляются в Erlang с помощью других типов данных, например, wxPoint задаётся в виде кортежа из двух элементов. События в wxErlang могут быть обработаны в Erlang либо с помощью функций обратного вызова ({{lang-en|call-back functions}}), либо более естественной в среде Erlang передачей сообщений{{sfn|Чезарини, Томпсон|2012|с=337-339,348}}.
Разработка приложений с [[GUI|графическим интерфейсом пользователя]] (не считая [[веб-интерфейс]]ов) может вестись при помощи библиотеки wxErlang — библиотеки [[wxWidgets]], портированной для Erlang. WxErlang входит в стандартную поставку Erlang/OTP. WxWidgets написан на [[C++]], поэтому перед разработчиками wxErlang стояла задача выразить средствами Erlang иерархию [[объект (программирование)|объектов]]. Несколько упрощая, в wxErlang [[класс (программирование)|классам]] соответствуют модули, а объектам — ссылки. Макросам на C++ соответствуют макросы Erlang. Некоторые типы данных, для которых в C++ были использованы классы, представляются в Erlang с помощью других типов данных, например, wxPoint задаётся в виде кортежа из двух элементов. События в wxErlang могут быть обработаны в Erlang либо с помощью функций обратного вызова ({{lang-en|call-back functions}}), либо более естественной в среде Erlang передачей сообщений{{sfn|Чезарини, Томпсон|2012|с=337—339,348}}.


== Программирование на Erlang ==
== Программирование на Erlang ==
Строка 579: Строка 580:
=== Интерактивная оболочка ===
=== Интерактивная оболочка ===
[[Файл:Erlang erl.png|мини|справа|440пкс|Интерактивная оболочка erl в отдельном окне]]
[[Файл:Erlang erl.png|мини|справа|440пкс|Интерактивная оболочка erl в отдельном окне]]
Интерактивная оболочка ({{lang-en|shell}}) для Erlang может быть вызвана в [[Unix-подобная операционная система|Unix-подобных системах]] по команде <code>erl</code>, в Windows — <code>werl</code>{{sfn|Simon St. Laurent|2013|с=2-3}}. В оболочке можно вводить выражения и получать результат их выполнения, опробовать новый код, заниматься интерактивной отладкой, а также управлять системой, находящейся в промышленной эксплуатации{{sfn|Martin Logan, et al|2011|p=23-27}}.
Интерактивная оболочка ({{lang-en|shell}}) для Erlang может быть вызвана в [[Unix-подобная операционная система|Unix-подобных системах]] по команде <code>erl</code>, в Windows — <code>werl</code>{{sfn|Simon St. Laurent|2013|с=2—3}}. В оболочке можно вводить выражения и получать результат их выполнения, опробовать новый код, заниматься интерактивной отладкой, а также управлять системой, находящейся в промышленной эксплуатации{{sfn|Martin Logan, et al|2011|p=23—27}}.


В оболочке можно использовать дополнительные функции («команды»), доступные только в ней. Например, команда <code>q().</code> осуществляет выход из оболочки с завершением всего, что делает Erlang-система{{sfn|Martin Logan, et al|2011|p=23-27}}.
В оболочке можно использовать дополнительные функции («команды»), доступные только в ней. Например, команда <code>q().</code> осуществляет выход из оболочки с завершением всего, что делает Erlang-система{{sfn|Martin Logan, et al|2011|p=23—27}}.


В оболочке можно вызвать BREAK-меню с помощью {{key|Ctrl|C}} (в Unix-подобных ОС) или {{key|Ctrl|Break}} (в Windows). В этом меню есть различные команды, в том числе {{key|a}} — немедленный останов, {{key|c}} — продолжение работы в оболочке и другие информационные и вспомогательные команды для работы с Erlang-системой{{sfn|Martin Logan, et al|2011|p=23-27}}. Комбинацией клавиш {{key|Ctrl|G}} вызывается ещё одно командное меню, с помощью которого можно, среди прочего, остановить «завесивший» оболочку процесс и вернуться в оболочку ({{key|i}} и затем {{key|c}}){{sfn|Hebert|2013|loc=Starting Out}}.
В оболочке можно вызвать BREAK-меню с помощью {{key|Ctrl|C}} (в Unix-подобных ОС) или {{key|Ctrl|Break}} (в Windows). В этом меню есть различные команды, в том числе {{key|a}} — немедленный останов, {{key|c}} — продолжение работы в оболочке и другие информационные и вспомогательные команды для работы с Erlang-системой{{sfn|Martin Logan, et al|2011|p=23—27}}. Комбинацией клавиш {{key|Ctrl|G}} вызывается ещё одно командное меню, с помощью которого можно, среди прочего, остановить «завесивший» оболочку процесс и вернуться в оболочку ({{key|i}} и затем {{key|c}}){{sfn|Hebert|2013|loc=Starting Out}}.


=== Документирование и оформление кода ===
=== Документирование и оформление кода ===
Текст от знака процента (<code>%</code>) до конца строки считается комментарием в Erlang. Генерация документации из исходного кода в Erlang может производиться системой документирования EDoc. Для документирования кода модуля достаточно добавить определённым образом размеченный текст, а также файл <code>overview.edoc</code> для документации уровня проекта (в последнем необязательно использовать знаки комментария){{sfn|Simon St. Laurent|2013|с=20-21}}. Инструменты для работы с кодом на Erlang, например, erlang-режим в [[Emacs]], подразумевают некоторые соглашения по употреблению символов комментария. Так, утроенный знак процента вызывает выравнивание по левому краю, удвоенный — выравнивание на уровне окружающего кода, а одиночный знак процента используется для обозначения комментария после кода, в конце строки{{sfn|Simon St. Laurent|2013|с=21}}. Разработчики Erlang выработали определённые [[стиль программирования|стилевые соглашения]], касающиеся организации и оформления исходного кода. Например, хорошим стилем считается понижение вложенности синтаксических структур, написание коротких модулей (менее 400 строк кода) и функций (не длиннее 15-20 строк кода), использование осмысленных имён для переменных и функций и т. п.<ref>{{cite web|url=http://erlang.se/doc/programming_rules.shtml|title=Programming Rules and Conventions|publisher=Ericsson AB|author=Klas Eriksson, M. Williams, J. Armstrong}}</ref>{{sfn|Чезарини, Томпсон|2012|с=460-465}}
Текст от знака процента (<code>%</code>) до конца строки считается комментарием в Erlang. Генерация документации из исходного кода в Erlang может производиться системой документирования EDoc. Для документирования кода модуля достаточно добавить определённым образом размеченный текст, а также файл <code>overview.edoc</code> для документации уровня проекта (в последнем необязательно использовать знаки комментария){{sfn|Simon St. Laurent|2013|с=20—21}}. Инструменты для работы с кодом на Erlang, например, erlang-режим в [[Emacs]], подразумевают некоторые соглашения по употреблению символов комментария. Так, утроенный знак процента вызывает выравнивание по левому краю, удвоенный — выравнивание на уровне окружающего кода, а одиночный знак процента используется для обозначения комментария после кода, в конце строки{{sfn|Simon St. Laurent|2013|с=21}}. Разработчики Erlang выработали определённые [[стиль программирования|стилевые соглашения]], касающиеся организации и оформления исходного кода. Например, хорошим стилем считается понижение вложенности синтаксических структур, написание коротких модулей (менее 400 строк кода) и функций (не длиннее 15-20 строк кода), использование осмысленных имён для переменных и функций и т. п.<ref>{{cite web|url=http://erlang.se/doc/programming_rules.shtml|title=Programming Rules and Conventions|publisher=Ericsson AB|author=Klas Eriksson, M. Williams, J. Armstrong|access-date=2013-12-02|archive-date=2013-11-30|archive-url=https://web.archive.org/web/20131130121046/http://www.erlang.se/doc/programming_rules.shtml|deadlink=no}}</ref>{{sfn|Чезарини, Томпсон|2012|с=460—465}}


=== Типы и анализ кода ===
=== Типы и анализ кода ===
Приложение Dialyzer, разработанное в рамках проекта HiPE и входящее в стандартную поставку, позволяет выявить ошибки (в том числе ошибки типизации) путём [[статический анализ кода|статического анализа кода]]. Программа TypEr, написанная Тобиасом Линдалом (Tobias Lindahl) и Костисом Сагонасом (Kostis Sagonas), является частью Dialyzer. Эта программа позволяет проверять определения типов функций, сверять указанный в директиве <code>-spec</code> тип функции с её определением, выполнить вывод типов{{sfn|Чезарини, Томпсон|2012|с=424-430}}. Программа TypEr выводит все типы, соответствующие успешному применению функции, в общем случае — лишь приблизительно, в более грубую сторону. Использование функции любым другим способом обязательно приведёт к ошибке времени исполнения{{sfn|Чезарини, Томпсон|2012|с=424-430}}. В следующем примере показан синтаксис определения типа (директива <code>-type</code>), объявление типа полей записи и директива <code>-spec</code> вместе с определением функции:
Приложение Dialyzer, разработанное в рамках проекта HiPE и входящее в стандартную поставку, позволяет выявить ошибки (в том числе ошибки типизации) путём [[статический анализ кода|статического анализа кода]]. Программа TypEr, написанная Тобиасом Линдалом (Tobias Lindahl) и Костисом Сагонасом (Kostis Sagonas), является частью Dialyzer. Эта программа позволяет проверять определения типов функций, сверять указанный в директиве <code>-spec</code> тип функции с её определением, выполнить вывод типов{{sfn|Чезарини, Томпсон|2012|с=424—430}}. Программа TypEr выводит все типы, соответствующие успешному применению функции, в общем случае — лишь приблизительно, в более грубую сторону. Использование функции любым другим способом обязательно приведёт к ошибке времени исполнения{{sfn|Чезарини, Томпсон|2012|с=424—430}}. В следующем примере показан синтаксис определения типа (директива <code>-type</code>), объявление типа полей записи и директива <code>-spec</code> вместе с определением функции:


<syntaxhighlight lang="Erlang">
<syntaxhighlight lang="erlang" line="1">
-type(user_status() :: disabled | enabled). % статус - один из двух атомов
-type(user_status() :: disabled | enabled). % статус - один из двух атомов


Строка 610: Строка 611:
Erlang предоставляет EUnit для [[модульное тестирование|модульного тестирования]] и фреймворк Common Test для [[системное тестирование|системного тестирования]]. EUnit содержит средства для описания тестов, включая необходимый для этого набор макросов, а также производит вывод отчёта по окончании тестирования. Тестирование модулей происходит путём подключения заголовочного файла из EUnit, а функции с тестами могут быть как включены в сам тестируемый модуль, а так и вынесены в отдельный{{sfn|Чезарини, Томпсон|2012|с=442}}.
Erlang предоставляет EUnit для [[модульное тестирование|модульного тестирования]] и фреймворк Common Test для [[системное тестирование|системного тестирования]]. EUnit содержит средства для описания тестов, включая необходимый для этого набор макросов, а также производит вывод отчёта по окончании тестирования. Тестирование модулей происходит путём подключения заголовочного файла из EUnit, а функции с тестами могут быть как включены в сам тестируемый модуль, а так и вынесены в отдельный{{sfn|Чезарини, Томпсон|2012|с=442}}.


Тестирование параллельных программ можно выполнить с помощью Quviq Quick Check (версия Mini этого продукта доступна бесплатно){{sfn|Чезарини, Томпсон|2012|с=449-450}}. Кроме тестирования, можно провести проверку всех возможных вариантов исходных данных с помощью метода [[проверка моделей|проверки моделей]]. Для этого можно воспользоваться созданной в Мадридском политехническом университете отдельно распространяемой утилитой McErlang{{sfn|Чезарини, Томпсон|2012|с=449-450,478}}.
Тестирование параллельных программ можно выполнить с помощью Quviq Quick Check (версия Mini этого продукта доступна бесплатно){{sfn|Чезарини, Томпсон|2012|с=449—450}}. Кроме тестирования, можно провести проверку всех возможных вариантов исходных данных с помощью метода [[проверка моделей|проверки моделей]]. Для этого можно воспользоваться созданной в Мадридском политехническом университете отдельно распространяемой утилитой McErlang{{sfn|Чезарини, Томпсон|2012|с=449—450,478}}.


Для [[профилирование (информатика)|профилирования]] кода и выявления степени [[тестирование программного обеспечения#Покрытие кода|покрытия кода тестами]] можно обратиться к модулям <code>eprof</code>, <code>fprof</code>, <code>cover</code> и [[утилита|утилите]] cprof{{sfn|Simon St. Laurent|2013|с=166-167}}.
Для [[профилирование (информатика)|профилирования]] кода и выявления степени [[тестирование программного обеспечения#Покрытие кода|покрытия кода тестами]] можно обратиться к модулям <code>eprof</code>, <code>fprof</code>, <code>cover</code> и [[утилита|утилите]] cprof{{sfn|Simon St. Laurent|2013|с=166—167}}.


Для Erlang разработаны несколько инструментов [[рефакторинг]]а исходного кода, такие как RefactorErl, Wrangler, а также автоматическая, независимая от [[Интегрированная среда разработки|IDE]] утилита tidier. Утилита tidier позволяет автоматически находить и производить эквивалентные преобразование кода, например, заменяет
Для Erlang разработаны несколько инструментов [[рефакторинг]]а исходного кода, такие как RefactorErl, Wrangler, а также автоматическая, независимая от [[Интегрированная среда разработки|IDE]] утилита tidier. Утилита tidier позволяет автоматически находить и производить эквивалентные преобразование кода, например, заменяет
Строка 625: Строка 626:
Как и многие другие языки программирования, Erlang имеет свои секреты написания эффективного кода. Совершенствование языка делает некоторые из трюков устаревшими, поэтому документация является лучшим руководством в вопросах оптимизации, в совокупности с профилированием и [[стресс-тестирование программного обеспечения|стресс-тестированием]].
Как и многие другие языки программирования, Erlang имеет свои секреты написания эффективного кода. Совершенствование языка делает некоторые из трюков устаревшими, поэтому документация является лучшим руководством в вопросах оптимизации, в совокупности с профилированием и [[стресс-тестирование программного обеспечения|стресс-тестированием]].


Например, при работе со списками не рекомендуется добавлять элемент в конец длинного списка с помощью конкатенации или функции добавления элемента к списку. Вместо этого сто{{удар}}ит рассмотреть возможность добавления элемента в начало списка, а конечный результат обработать функцией обращения порядка элементов списка{{sfn|Чезарини, Томпсон|2012|с=470}}.
Например, при работе со списками не рекомендуется добавлять элемент в конец длинного списка с помощью конкатенации или функции добавления элемента к списку. Вместо этого сто́ит рассмотреть возможность добавления элемента в начало списка, а конечный результат обработать функцией обращения порядка элементов списка{{sfn|Чезарини, Томпсон|2012|с=470}}.


Свои рекомендации есть и для увеличения эффективности параллельных программ. Например, действия, требующие много памяти, лучше всего выделять в отдельный процесс, так как при этом затраты на сборку мусора будут минимальны: память будет освобождена по завершению процесса{{sfn|Чезарини, Томпсон|2012|с=471}}.
Свои рекомендации есть и для увеличения эффективности параллельных программ. Например, действия, требующие много памяти, лучше всего выделять в отдельный процесс, так как при этом затраты на сборку мусора будут минимальны: память будет освобождена по завершении процесса{{sfn|Чезарини, Томпсон|2012|с=471}}.


== Erlang и другие языки программирования ==
== Erlang и другие языки программирования ==
Строка 633: Строка 634:


=== Интеграция и гибридные языки ===
=== Интеграция и гибридные языки ===
Erlang-система позволяет выполнять интеграцию с системами на других языках программирования. Имеются механизмы для сетевого взаимодействия с [[Си (язык программирования)|Си]], [[Java]], [[Лисп]], [[Perl]], [[Python]], [[Ruby]]. Например, для более эффективного синхронного вызова небольших функций на Си можно использовать платформно-зависимые функции ({{lang-en|NIF, natively implemented function}}). Высокоуровневые библиотеки позволяют Erlang-системе представлять С или Java-узлы как обычные Erlang-узлы. Другие языки могут быть более тесно сопряжены со средой выполнения Erlang с помощью драйверов или сетевых [[сокет (программный интерфейс)|сокетов]] посредством протоколов вроде [[HTTP]], [[SNMP]], [[GIOP|IIOP]]{{sfn|Чезарини, Томпсон|2012|с=31}}. Например, Ruby может взаимодействовать с Erlang посредством пакета erlectricity, а для Python разработана реализация Erlang-узла в виде пакета py-interface{{sfn|Zachary Kessin|2012|p=125-128}}.
Erlang-система позволяет выполнять интеграцию с системами на других языках программирования. Имеются механизмы для сетевого взаимодействия с [[Си (язык программирования)|Си]], [[Java]], [[Лисп]], [[Perl]], [[Python]], [[Ruby]]. Например, для более эффективного синхронного вызова небольших функций на Си можно использовать платформно-зависимые функции ({{lang-en|NIF, natively implemented function}}). Высокоуровневые библиотеки позволяют Erlang-системе представлять С или Java-узлы как обычные Erlang-узлы. Другие языки могут быть более тесно сопряжены со средой выполнения Erlang с помощью драйверов или сетевых [[сокет (программный интерфейс)|сокетов]] посредством протоколов вроде [[HTTP]], [[SNMP]], [[GIOP|IIOP]]{{sfn|Чезарини, Томпсон|2012|с=31}}. Например, Ruby может взаимодействовать с Erlang посредством пакета erlectricity, а для Python разработана реализация Erlang-узла в виде пакета py-interface{{sfn|Zachary Kessin|2012|p=125—128}}.


Виртуальная машина Erlang находит применение и в других языках программирования, например, [[Elixir (язык программирования)|Elixir]]<ref>{{cite web|url=http://elixir-lang.org/|title=elixir|date=2013|publisher=Plataformatec|accessdate=2013-12-01|lang=en}}</ref>{{sfn|Simon St. Laurent|2013|с=168}} и проекте Erl2 Джо Армстронга<ref>{{cite web|url=https://github.com/joearms/erl2|title=erl2, a new dialect of erlang|date=2013|author=Joe Armstrong|accessdate=2013-12-01|lang=en}}</ref>{{sfn|Simon St. Laurent|2013|с=168}}. Кроме того, Роберт Вирдинг поддерживает проект Lisp Flavored Erlang («Erlang, приправленный Лиспом»), в котором синтаксис [[Лисп]]а используется с компилятором Erlang<ref>{{cite web|url=http://lfe.github.io/|title= Lisp Flavored Erlang||accessdate=2013-12-08|lang=en}}</ref>. Есть и другие BEAM-языки: Efene, Joxa, Reia<ref>[http://www.unlimitednovelty.com/2011/06/why-im-stopping-work-on-reia.html Why I'm stopping work on Reia ], 2011</ref>, Luerl, Erlog<ref>Federico Carrone, et al [http://spawnedshelter.com/ Spawned Shelter!]</ref>.
Виртуальная машина Erlang находит применение и в других языках программирования, например, [[Elixir (язык программирования)|Elixir]]<ref>{{cite web|url=http://elixir-lang.org/|title=elixir|date=2013|publisher=Plataformatec|accessdate=2013-12-01|lang=en|archive-date=2012-04-18|archive-url=https://web.archive.org/web/20120418080914/http://elixir-lang.org/|deadlink=no}}</ref>{{sfn|Simon St. Laurent|2013|с=168}} и проекте Erl2 Джо Армстронга<ref>{{cite web|url=https://github.com/joearms/erl2|title=erl2, a new dialect of erlang|date=2013|author=Joe Armstrong|accessdate=2013-12-01|lang=en|archive-date=2013-09-05|archive-url=https://web.archive.org/web/20130905020619/https://github.com/joearms/erl2|deadlink=no}}</ref>{{sfn|Simon St. Laurent|2013|с=168}}. Кроме того, Роберт Вирдинг поддерживает проект Lisp Flavored Erlang («Erlang, приправленный Лиспом»), в котором синтаксис [[Лисп]]а используется с компилятором Erlang<ref>{{cite web|url=https://lfe.github.io/|title=Lisp Flavored Erlang|accessdate=2013-12-08|lang=en|archive-date=2013-12-13|archive-url=https://web.archive.org/web/20131213020344/http://lfe.github.io/|deadlink=no}}</ref>. Есть и другие BEAM-языки: Efene, Joxa, Reia<ref>[http://www.unlimitednovelty.com/2011/06/why-im-stopping-work-on-reia.html Why I’m stopping work on Reia ] {{Wayback|url=http://www.unlimitednovelty.com/2011/06/why-im-stopping-work-on-reia.html |date=20150915013337 }}, 2011</ref>, Luerl, Erlog<ref>Federico Carrone, et al [http://spawnedshelter.com/ Spawned Shelter!] {{Wayback|url=http://spawnedshelter.com/ |date=20151105061047 }}</ref>.


Официальный сайт упоминает<ref>{{cite web|url=http://www.erlang.org/faq/academic.html|title=Academic and Historical Questions|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en}}</ref> проект Erjang<ref>{{cite web|url=https://github.com/trifork/erjang/wiki|title=Welcome to Erjang!|date=2013|publisher=Trifork A/S|accessdate=2013-12-01|lang=en}}</ref>, в котором используется виртуальная машина Java.
Официальный сайт упоминает<ref>{{cite web|url=http://www.erlang.org/faq/academic.html|title=Academic and Historical Questions|date=2013|publisher=Ericsson AB|accessdate=2013-12-01|lang=en|archive-date=2013-10-06|archive-url=https://web.archive.org/web/20131006100712/http://www.erlang.org/faq/academic.html|deadlink=no}}</ref> проект Erjang<ref>{{cite web|url=https://github.com/trifork/erjang/wiki|title=Welcome to Erjang!|date=2013|publisher=Trifork A/S|accessdate=2013-12-01|lang=en|archive-date=2017-03-10|archive-url=https://web.archive.org/web/20170310052413/https://github.com/trifork/erjang/wiki|deadlink=no}}</ref>, в котором используется виртуальная машина Java.


=== Сравнение Erlang и C++ по производительности ===
=== Сравнение Erlang и C++ по производительности ===
Хотя опытные Erlang-программисты давно заметили, что их программы для тех же задач получаются более краткими по сравнению с другими широко используемыми в промышленности языками программирования, эмпирическое исследование показало, что для изученных телекоммуникационных приложений код на Erlang был на 70-85 % короче, чем на [[С++]], а производительность системы при переписывании кода с С++ на Erlang возросла почти на 100 %{{sfn|Nyström, Trinder, King|2008}}{{sfn|Чезарини, Томпсон|2012|с=35-36}}. Для одного из использованных в исследовании проектов разница была объяснена написанием дополнительного С++-кода в рамках [[defensive computing|защитного программирования]], управления памятью и кода для высокоуровневой коммуникации, то есть возможностями, которые являются частью языка Erlang и библиотек OTP{{sfn|Чезарини, Томпсон|2012|с=35-36}}.
Хотя опытные Erlang-программисты давно заметили, что их программы для тех же задач получаются более краткими по сравнению с другими широко используемыми в промышленности языками программирования, эмпирическое исследование показало, что для изученных телекоммуникационных приложений код на Erlang был на 70—85 % короче, чем на [[C++]], а производительность системы при переписывании кода с C++ на Erlang возросла почти на 100 %{{sfn|Nyström, Trinder, King|2008}}{{sfn|Чезарини, Томпсон|2012|с=35—36}}. Для одного из использованных в исследовании проектов разница была объяснена написанием дополнительного C++-кода в рамках [[defensive computing|защитного программирования]], управления памятью и кода для высокоуровневой коммуникации, то есть возможностями, которые являются частью языка Erlang и библиотек OTP{{sfn|Чезарини, Томпсон|2012|с=35—36}}.


=== Сравнение взаимодействия процессов в Erlang и Go ===
=== Сравнение взаимодействия процессов в Erlang и Go ===
Влияние [[взаимодействующие последовательные процессы|теории взаимодействующих последовательных процессов]] [[Хоар, Чарльз Энтони Ричард|Чарльза Э. Хоара]] чувствуется как в [[Go]], так и в Erlang. В Erlang процессы, в соответствии с моделью акторов, отправляют сообщения друг другу напрямую. В Go то же самое происходит посредством каналов ({{lang-en|channels}})<ref name="chisnall">{{cite web|url=http://www.informit.com/articles/article.aspx?p=1768317|author=David Chisnall|title=A Tale of Two Concurrency Models: Comparing the Go and Erlang Programming Languages|date=14-11-2011|publisher=Pearson Education, Informit|accessdate=2013-12-01|lang=en}}</ref>. Другим отличием является то, что каналы в Go имеют типы. В Erlang же нет типизации времени [[компиляция (программирование)|компиляции]] за исключением охранных выражений, что позволяет посылать процессам сообщения любого типа, но «непонятое» сообщение либо будет проигнорировано, либо навсегда останется в очереди<ref name="chisnall"/>. Go позволяет легко организовать группу «go-программ» ({{lang-en|goroutine}} — намёк на {{lang-en|co-routine}} — [[сопрограмма]]) для получения сообщений из некоторого канала (такой подход известен как [[пул потоков]]). В Erlang, при проектировании которого уделялось особое внимание [[детерминизм (информатика)|детерминизму]] и времени задержки ({{lang-en|latency}}), реализация рабочего пула возможна, но требует дополнительных усилий. Множественные отправители тривиально реализуются в обоих языках<ref name="chisnall"/>. Erlang-процесс может послать сообщение и ждать на него ответ (соответствующий некоторому образцу), игнорируя другие сообщения в очереди. В Go такое невозможно, но подобная функциональность может быть достигнута созданием (в том числе, динамическим) новых вводов, то есть разделением каналов по назначению<ref name="chisnall"/>. Go требует явного указания того, какие go-программы будут взаимодействовать с другими передачей сообщений, тогда как в Erlang отсутствует разделяемое между процессами изменяемое состояние ({{lang-en|shared mutable state}}) и поэтому изолированный процесс очень редко представляет интерес<ref name="chisnall"/>.
Влияние [[взаимодействующие последовательные процессы|теории взаимодействующих последовательных процессов]] [[Хоар, Чарльз Энтони Ричард|Чарльза Э. Хоара]] чувствуется как в [[Go]], так и в Erlang. В Erlang процессы, в соответствии с моделью акторов, отправляют сообщения друг другу напрямую. В Go то же самое происходит посредством каналов ({{lang-en|channels}})<ref name="chisnall">{{cite web|url=http://www.informit.com/articles/article.aspx?p=1768317|author=David Chisnall|title=A Tale of Two Concurrency Models: Comparing the Go and Erlang Programming Languages|date=2011-11-14|publisher=Pearson Education, Informit|accessdate=2013-12-01|lang=en|archive-date=2013-12-03|archive-url=https://web.archive.org/web/20131203213648/http://www.informit.com/articles/article.aspx?p=1768317|deadlink=no}}</ref>. Другим отличием является то, что каналы в Go имеют типы. В Erlang же нет типизации времени [[компиляция (программирование)|компиляции]] за исключением охранных выражений, что позволяет посылать процессам сообщения любого типа, но «непонятое» сообщение либо будет проигнорировано, либо навсегда останется в очереди<ref name="chisnall"/>. Go позволяет легко организовать группу «go-программ» ({{lang-en|goroutine}} — намёк на {{lang-en|co-routine}} — [[сопрограмма]]) для получения сообщений из некоторого канала (такой подход известен как [[пул потоков]]). В Erlang, при проектировании которого уделялось особое внимание [[детерминизм (информатика)|детерминизму]] и времени задержки ({{lang-en|latency}}), реализация рабочего пула возможна, но требует дополнительных усилий. Множественные отправители тривиально реализуются в обоих языках<ref name="chisnall"/>. Erlang-процесс может послать сообщение и ждать на него ответ (соответствующий некоторому образцу), игнорируя другие сообщения в очереди. В Go такое невозможно, но подобная функциональность может быть достигнута созданием (в том числе, динамическим) новых вводов, то есть разделением каналов по назначению<ref name="chisnall"/>. Go требует явного указания того, какие go-программы будут взаимодействовать с другими передачей сообщений, тогда как в Erlang отсутствует разделяемое между процессами изменяемое состояние ({{lang-en|shared mutable state}}) и поэтому изолированный процесс очень редко представляет интерес<ref name="chisnall"/>.


Абстракции взаимодействующих процессов достаточно похожи в Erlang и Go, однако во избежание ошибок при переходе с одного языка на другой следует учитывать нюансы: шаблоны, которые хороши в одном языке, могут не подходить для другого<ref name="chisnall"/>.
Абстракции взаимодействующих процессов достаточно похожи в Erlang и Go, однако во избежание ошибок при переходе с одного языка на другой следует учитывать нюансы: шаблоны, которые хороши в одном языке, могут не подходить для другого<ref name="chisnall"/>.


== Критика ==
== Критика ==
Как и любой язык программирования, Erlang не свободен от недостатков<ref name="Katz">{{cite web|url=http://damienkatz.net/2008/03/what_sucks_abou.html |title=What Sucks About Erlang|author=Damien Katz (создатель [[CouchDB]])|date=2008-03-09|lang=en}}</ref>. К погрешностям синтаксиса можно отнести зависимость от символа окончания выражения от контекста (это может быть <code>.</code>, <code>,</code> или <code>;</code>), что требует дополнительного внимания при перемене выражений местами, излишнюю многословность записей (тип записи приходится упоминать при каждом доступе к члену записи), необходимость полного перечисления альтернатив в if-выражении во избежание выбрасывания [[исключение (программирование)|исключения]], если ни одно из условий не выполнено. К недостаткам можно отнести строго ограниченный набор функций, которые можно использовать в if-выражениях (этот недостаток можно обойти использованием case-выражений). Функциональный стиль и неизменяемые переменные приводят в некоторых приложениях (например, тесты) к бо{{удар}}льшему количеству правок, чем в других языках программирования, так как вставка некоторой промежуточной обработки может потребовать новых имён переменных, что может привести к изменениям в коде, следующем далее по тексту. Из недостатков системы типов можно указать отсутствие [[строковый тип|строкового типа]], а также невозможность динамически добавлять в записи новые члены. Есть проблемы и с организацией исходного кода, которая возможна только через создание нового файла, а также отсутствие пространств имён, классов или других средств для организации кода. Уровень качества модулей, за исключением основных, и документации оставляет желать лучшего<ref name="Katz"/><!-- весь абзац по этому источнику -->.
Как и любой язык программирования, Erlang не свободен от недостатков<ref name="Katz">{{cite web|url=http://damienkatz.net/2008/03/what_sucks_abou.html|title=What Sucks About Erlang|author=Damien Katz (создатель [[CouchDB]])|date=2008-03-09|lang=en|access-date=2013-11-24|archive-date=2013-12-05|archive-url=https://web.archive.org/web/20131205040258/http://damienkatz.net/2008/03/what_sucks_abou.html|deadlink=no}}</ref>. К погрешностям синтаксиса можно отнести зависимость от символа окончания выражения от контекста (это может быть <code>.</code>, <code>,</code> или <code>;</code>), что требует дополнительного внимания при перемене выражений местами, излишнюю многословность записей (тип записи приходится упоминать при каждом доступе к члену записи), необходимость полного перечисления альтернатив в if-выражении во избежание выбрасывания [[исключение (программирование)|исключения]], если ни одно из условий не выполнено. К недостаткам можно отнести строго ограниченный набор функций, которые можно использовать в if-выражениях (этот недостаток можно обойти использованием case-выражений). Функциональный стиль и неизменяемые переменные приводят в некоторых приложениях (например, тесты) к бо́льшему количеству правок, чем в других языках программирования, так как вставка некоторой промежуточной обработки может потребовать новых имён переменных, что может привести к изменениям в коде, следующем далее по тексту. Из недостатков системы типов можно указать отсутствие [[строковый тип|строкового типа]], а также невозможность динамически добавлять в записи новые члены. Есть проблемы и с организацией исходного кода, которая возможна только через создание нового файла, а также отсутствие пространств имён, классов или других средств для организации кода. Уровень качества модулей, за исключением основных, и документации оставляет желать лучшего<ref name="Katz"/><!-- весь абзац по этому источнику -->.


Один из создателей языка, Джо Армстронг, в своём выступлении на конференции по истории языков программирования в 2007 году перечислил список областей, в которых Erlang можно было бы улучшить{{sfn|Armstrong, A History of Erlang|2007|loc=6-19,6-20}}:
Один из создателей языка, Джо Армстронг, в своём выступлении на конференции по истории языков программирования в 2007 году перечислил список областей, в которых Erlang можно было бы улучшить{{sfn|Armstrong, A History of Erlang|2007|loc=6-19,6-20}}:
Строка 666: Строка 667:


Можно сказать, что Erlang стал применяться для разработки [[облачные вычисления|облачных систем]] ещё до того, как сформировалось само понятие облачных вычислений<ref name="гифт">{{cite web
Можно сказать, что Erlang стал применяться для разработки [[облачные вычисления|облачных систем]] ещё до того, как сформировалось само понятие облачных вычислений<ref name="гифт">{{cite web
|url = http://www.ibm.com/developerworks/ru/library/cl-bigdata/index.html
|url = http://www.ibm.com/developerworks/ru/library/cl-bigdata/index.html
|title = Работа с большими объемами данных в облаке с помощью MapReduce
|title = Работа с большими объемами данных в облаке с помощью MapReduce
|author = Ной Гифт
|author = Ной Гифт
|date = 01.03.2012
|date = 2012-03-01
|publisher = IBM
|publisher = IBM
|accessdate = 2013-12-07
|accessdate = 2013-12-07
|archive-date = 2013-12-11
}}</ref>. Язык Erlang используется в масштабных телекоммуникационных и Интернет-приложениях многими компаниями, включая [[Amazon EC2]] с реализацией [[SimpleDB]], сервис социальных закладок [[Delicious]], [[Facebook]] (бэкенд для чата), [[T-Mobile]] (сервис [[SMS]] и системы аутентификации){{sfn|Чезарини, Томпсон|2012|с=23-25}}. Серверное программное обеспечение [[WhatsApp]] написано на Erlang. В январе 2012 года серверы WhatsApp под [[FreeBSD]] с 96 ГБ оперативной памяти смогли обрабатывать от 1 до 2,8 миллионов соединений<ref>[http://www.erlang-factory.com/upload/presentations/558/efsf2012-whatsapp-scaling.pdf Scaling to Millions of Simultaneous Connections], Rick Reed (WhatsApp) // Erlang Factory SF, March 30, 2012</ref><ref>[http://blog.whatsapp.com/index.php/2012/01/1-million-is-so-2011/ 1 million is so 2011] // WhatsApp Blog, January 6, 2012</ref>.
|archive-url = https://web.archive.org/web/20131211043500/http://www.ibm.com/developerworks/ru/library/cl-bigdata/index.html
|deadlink = no
}}</ref>. Язык Erlang используется в масштабных телекоммуникационных и Интернет-приложениях многими компаниями, включая [[Amazon EC2]] с реализацией [[SimpleDB]], сервис социальных закладок [[Delicious]], [[Facebook]] (бэкенд для чата), [[T-Mobile]] (сервис [[SMS]] и системы аутентификации){{sfn|Чезарини, Томпсон|2012|с=23—25}}. Серверное программное обеспечение [[WhatsApp]] написано на Erlang. В январе 2012 года серверы WhatsApp под [[FreeBSD]] с 96 ГБ оперативной памяти смогли обрабатывать от 1 до 2,8 миллиона соединений<ref>[http://www.erlang-factory.com/upload/presentations/558/efsf2012-whatsapp-scaling.pdf Scaling to Millions of Simultaneous Connections] {{Wayback|url=http://www.erlang-factory.com/upload/presentations/558/efsf2012-whatsapp-scaling.pdf |date=20120709235656 }}, Rick Reed (WhatsApp) // Erlang Factory SF, March 30, 2012</ref><ref>[http://blog.whatsapp.com/index.php/2012/01/1-million-is-so-2011/ 1 million is so 2011] {{Wayback|url=http://blog.whatsapp.com/index.php/2012/01/1-million-is-so-2011/ |date=20140219234031 }} // WhatsApp Blog, January 6, 2012</ref>.


Erlang часто ставят в заслугу легендарную надёжность ATM-коммутатора AXD301 (полтора миллиона строк кода на Erlang, полмиллиона — на C/C++) в сети [[British Telecom]]. По данным Ericsson, с момента установки в январе 2002 года за несколько лет<!-- источник не приводит по какой год данные --> случилась только одна незначительная неполадка, на основании чего надёжность системы по расчётам составила 99,9999999 %{{sfn|Чезарини, Томпсон|2012|с=33}}. Хотя более реальные оценки, учитывающие многие другие факторы, говорят всё-таки о «пяти девятках», успех маршрутизатора связывают с легкодоступными средствами разработки надёжных параллельных вычислений, встроенными в Erlang{{sfn|Чезарини, Томпсон|2012|с=33}}.
Erlang часто ставят в заслугу легендарную надёжность ATM-коммутатора AXD301 (полтора миллиона строк кода на Erlang, полмиллиона — на C/C++) в сети [[British Telecom]]. По данным Ericsson, с момента установки в январе 2002 года за несколько лет<!-- источник не приводит по какой год данные --> случилась только одна незначительная неполадка, на основании чего надёжность системы по расчётам составила 99,9999999 %{{sfn|Чезарини, Томпсон|2012|с=33}}. Хотя более реальные оценки, учитывающие многие другие факторы, говорят всё-таки о «пяти девятках», успех маршрутизатора связывают с легкодоступными средствами разработки надёжных параллельных вычислений, встроенными в Erlang{{sfn|Чезарини, Томпсон|2012|с=33}}.
Строка 678: Строка 682:
Используется Erlang и в приложениях [[открытое программное обеспечение|с открытым исходным кодом]], среди которых [[CouchDB]] — документо-ориентированная база данных с [[REST]]-интерфейсом, [[Disco]] — фреймворк для распределённых вычислений на основе парадигмы [[MapReduce]]<ref name="гифт"/><ref>{{cite web
Используется Erlang и в приложениях [[открытое программное обеспечение|с открытым исходным кодом]], среди которых [[CouchDB]] — документо-ориентированная база данных с [[REST]]-интерфейсом, [[Disco]] — фреймворк для распределённых вычислений на основе парадигмы [[MapReduce]]<ref name="гифт"/><ref>{{cite web
|url = http://discoproject.org/
|url = http://discoproject.org/
|title = Disco (страница проекта)
|title = Disco (страница проекта)
|accessdate = 2013-12-07
|accessdate = 2013-12-07
|archive-date = 2010-09-16
}}</ref>, [[Ejabberd]] — свободный (GNU GPL), распределённый и устойчивый к отказам Jabber-сервер, написанный в основном на Erlang, [[RabbitMQ]] — [[Message Oriented Middleware|платформа, ориентированная на обработку сообщений]] (реализует [[AMQP]], [[MQTT]]<ref>{{cite web|author=Pivotal Software, Inc.|title=RabbitMQ MQTT Adapter|url=https://www.rabbitmq.com/mqtt.html}}</ref>), [[Wings 3D]] — программа 3D-моделирования и другие.{{sfn|Чезарини, Томпсон|2012|с=23-25}}
|archive-url = https://web.archive.org/web/20100916105505/http://discoproject.org/
|deadlink = no
}}</ref>, [[Ejabberd]] — свободный (GNU GPL), распределённый и устойчивый к отказам Jabber-сервер, написанный в основном на Erlang, [[RabbitMQ]] — [[Message Oriented Middleware|платформа, ориентированная на обработку сообщений]] (реализует [[AMQP]], [[MQTT]]<ref>{{cite web|author=Pivotal Software, Inc.|title=RabbitMQ MQTT Adapter|url=https://www.rabbitmq.com/mqtt.html|access-date=2015-12-10|archive-date=2015-12-01|archive-url=https://web.archive.org/web/20151201005325/http://www.rabbitmq.com/mqtt.html|deadlink=no}}</ref>), [[Wings 3D]] — программа 3D-моделирования и другие.{{sfn|Чезарини, Томпсон|2012|с=23—25}}


Для Erlang были написаны несколько [[веб-сервер]]ов: [[Yaws]] ({{lang-en|Yet Another Web Server}}), [[Cowboy (веб-сервер)|Cowboy]], а также [[MochiWeb]] — библиотека для создания HTTP-серверов<ref>{{cite web|url=http://www.ibm.com/developerworks/xml/library/os-erlang2/|title=Introduction to programming in Erlang, Part 2: Use advanced features and functionality|date=2013|author=Martin Brown|publisher=[[IBM]]|accessdate=2013-12-01|lang=en}}</ref>. Кроме того, были созданы несколько [[веб-фреймворк]]ов и [[система управления содержимым|систем управления содержимым]], таких как N2O<ref>{{cite web|url=http://www.linux.org.ru/news/opensource/9206001|title=Выпущен новый веб-фреймворк N2O на языке Erlang|publisher=linux.org.ru|accessdate=2014-12-13}}</ref>, [[Nitrogen (программный каркас)|Nitrogen]], [[Chicago Boss]], [[Zotonic]], а также более не разрабатываемые активно BeepBeep, Erlang Web, ErlyWeb{{sfn|Zachary Kessin|2012|p=121-123}}.
Для Erlang были написаны несколько [[веб-сервер]]ов: [[Yaws]] ({{lang-en|Yet Another Web Server}}), [[Cowboy (веб-сервер)|Cowboy]], а также [[MochiWeb]] — библиотека для создания HTTP-серверов<ref>{{cite web|url=http://www.ibm.com/developerworks/xml/library/os-erlang2/|title=Introduction to programming in Erlang, Part 2: Use advanced features and functionality|date=2013|author=Martin Brown|publisher=[[IBM]]|accessdate=2013-12-01|lang=en|archive-date=2013-12-03|archive-url=https://web.archive.org/web/20131203133348/http://www.ibm.com/developerworks/xml/library/os-erlang2/|deadlink=no}}</ref>. Кроме того, были созданы несколько [[веб-фреймворк]]ов и [[система управления содержимым|систем управления содержимым]], таких как N2O<ref>{{cite web|url=http://www.linux.org.ru/news/opensource/9206001|title=Выпущен новый веб-фреймворк N2O на языке Erlang|publisher=linux.org.ru|accessdate=2014-12-13|archive-date=2014-12-14|archive-url=https://web.archive.org/web/20141214004841/http://www.linux.org.ru/news/opensource/9206001|deadlink=no}}</ref>, [[Nitrogen (программный каркас)|Nitrogen]], [[Chicago Boss]], [[Zotonic]], а также более не разрабатываемые активно BeepBeep, Erlang Web, ErlyWeb{{sfn|Zachary Kessin|2012|p=121—123}}.


Среди другого известного программного обеспечения, выполненного на Erlang, можно выделить распределённую [[NoSQL]] базу данных [[Riak]], спроектированную по принципам [[Amazon DynamoDB]]{{sfn|Simon St. Laurent|2013|с=167}}, [[Flussonic]] (ранее известный как [[Erlyvideo]]) — видеостриминговый сервер, поддерживающий несколько протоколов<ref>{{cite web|url=http://erlyvideo.ru/|title=Flussonic — мультипротокольный видеостриминговый сервер|publisher=Flussonic, LLC}}</ref>. Для [[стресс-тестирование программного обеспечения|стресс-тестирования]] распределённых систем можно применять (также распределённый) написанный на Erlang инструмент [[Tsung]], который позволяет эмулировать тысячи (при достаточном количестве тестовых серверов — миллионы) одновременных пользователей<ref>{{книга
Среди другого известного программного обеспечения, выполненного на Erlang, можно выделить распределённую [[NoSQL]] базу данных [[Riak]], спроектированную по принципам [[Amazon DynamoDB]]{{sfn|Simon St. Laurent|2013|с=167}}, [[Flussonic]] (ранее известный как [[Erlyvideo]]) — видеостриминговый сервер, поддерживающий несколько протоколов<ref>{{cite web|url=http://erlyvideo.ru/|title=Flussonic — мультипротокольный видеостриминговый сервер|publisher=Flussonic, LLC|access-date=2012-05-07|archive-date=2012-06-16|archive-url=https://web.archive.org/web/20120616192637/http://erlyvideo.ru/|deadlink=no}}</ref>. Для [[стресс-тестирование программного обеспечения|стресс-тестирования]] распределённых систем можно применять (также распределённый) написанный на Erlang инструмент [[Tsung]], который позволяет эмулировать тысячи (при достаточном количестве тестовых серверов — миллионы) одновременных пользователей<ref>{{книга
| автор = Bradley Holt
| автор = Bradley Holt
| часть = Chapter 6. Distributed Load Testing
| часть = Chapter 6. Distributed Load Testing
| заглавие = Scaling CouchDB
| заглавие = Scaling CouchDB
| ссылка = https://archive.org/details/scalingcouchdb00holt
| издательство = O'Reilly Media, Inc.
| издательство = O'Reilly Media, Inc.
| год = 2011
| год = 2011
| pages = 39
| pages = [https://archive.org/details/scalingcouchdb00holt/page/n52 39]
| allpages = 72
| allpages = 72
| isbn = 978-1-4493-0343-3
| isbn = 978-1-4493-0343-3
Строка 696: Строка 704:
}}</ref>.
}}</ref>.


Erlang практически идеально подходят для задач [[искусственный интеллект|искусственного интеллекта]] (особенно [[вычислительный интеллект|вычислительного интеллекта]], [[нейроэволюция|нейроэволюции]]), основанных на [[искусственная нейронная сеть|нейронных сетях]]. Подобное применение возможно благодаря имеющимся у Erlang пяти ключевым свойствам «языка программирования нейронных сетей»: изолированные процессы-нейроны ({{lang-en|encapsulation}}), параллелизм ({{lang-en|concurrency}}, одновременность), механизм обнаружения сбоев, независимость от местоположения ({{lang-en|location transparency}}) и горячая замена кода. Примером такого применения является реализация одного из подходов к нейроэволюции — DXNN{{sfn|Sher|2013|loc=Chapter 5 The Unintentional Neural Network Programming Language|pp=144-150}}.
Erlang практически идеально подходят для задач [[искусственный интеллект|искусственного интеллекта]] (особенно [[вычислительный интеллект|вычислительного интеллекта]], [[нейроэволюция|нейроэволюции]]), основанных на [[искусственная нейронная сеть|нейронных сетях]]. Подобное применение возможно благодаря имеющимся у Erlang пяти ключевым свойствам «языка программирования нейронных сетей»: изолированные процессы-нейроны ({{lang-en|encapsulation}}), параллелизм ({{lang-en|concurrency}}, одновременность), механизм обнаружения сбоев, независимость от местоположения ({{lang-en|location transparency}}) и горячая замена кода. Примером такого применения является реализация одного из подходов к нейроэволюции — DXNN{{sfn|Sher|2013|loc=Chapter 5 The Unintentional Neural Network Programming Language|pp=144—150}}.


== Сообщество ==
== Сообщество ==
Вокруг технологий Erlang образовалось сообщество разработчиков, не отказывающее в поддержке новичкам. [[Исходный код]] Erlang доступен через сервис совместной разработки [[GitHub]]. Разработчики и пользователи Erlang могу общаться через список рассылки Erlang-questions (вопросы по Erlang) или на IRC-канале #erlang на [[Freenode]]. Erlang Factory (www.erlang-factory.com) устраивает по всему миру мероприятия и конференции, среди которых конференция пользователей Erlang (Erlang User Conference). Специальная группа SIGPLAN [[ACM]] регулярно проводит Erlang-мастерскую (Erlang Workshop), а конференция [[O’Reilly Open Source Convention|OSCON]] включает секцию по Erlang{{sfn|Simon St. Laurent|2013|с=168-169}}.
Вокруг технологий Erlang образовалось сообщество разработчиков, не отказывающее в поддержке новичкам. [[Исходный код]] Erlang доступен через сервис совместной разработки [[GitHub]]. Разработчики и пользователи Erlang могут общаться через список рассылки Erlang-questions (вопросы по Erlang) или на IRC-канале #erlang на [[Freenode]]. Erlang Factory (www.erlang-factory.com) устраивает по всему миру мероприятия и конференции, среди которых конференция пользователей Erlang (Erlang User Conference). Специальная группа SIGPLAN [[ACM]] регулярно проводит Erlang-мастерскую (Erlang Workshop), а конференция [[O’Reilly Open Source Convention|OSCON]] включает секцию по Erlang{{sfn|Simon St. Laurent|2013|с=168—169}}.


== Примечания ==
== Примечания ==
Строка 729: Строка 737:
|издательство = ДМК Пресс
|издательство = ДМК Пресс
|ref=Хеберт
|ref=Хеберт
|nodot = 1
}}
* {{книга
| автор = Чезарини Ф., Виноски С.
| заглавие = Проектирования масштабируемых систем в Erlang/OTP
| оригинал = Designing for Scalability with Erlang/OTP
| издание =
| издательство = [[ДМК Пресс]]
| год = 2017
| страниц = 486
| isbn = 978-5-97060-212-6
}}
}}
; на английском языке
; на английском языке
Строка 743: Строка 762:
| автор = Joe Armstrong
| автор = Joe Armstrong
| заглавие = Programming Erlang: Software for a Concurrent World
| заглавие = Programming Erlang: Software for a Concurrent World
| ссылка = https://archive.org/details/programmingerlan0000arms
| издательство = Pragmatic Bookshelf
| издательство = Pragmatic Bookshelf
| год = 2007
| год = 2007
Строка 752: Строка 772:
| автор = Bruce A. Tate
| автор = Bruce A. Tate
| заглавие = Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages
| заглавие = Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages
| ссылка = https://archive.org/details/sevenlanguagesin00tate
| издательство = Pragmatic Bookshelf
| издательство = Pragmatic Bookshelf
| год = 2010
| год = 2010
| allpages =
| allpages =
| isbn = 9781934356593
| isbn = 9781934356593
| ref = Tate
| ref = Tate
Строка 817: Строка 838:


* {{книга
* {{книга
| автор = Robert Virding, Claes Wikström, Mike Williams
| автор = Robert Virding, Claes Wikström, Mike Williams
| заглавие = Concurrent Programming in ERLANG
| заглавие = Concurrent Programming in ERLANG
| издание = 2nd ed
| издание = 2nd ed
Строка 838: Строка 859:


== Статьи ==
== Статьи ==
* {{статья |автор=Дмитрий Васильев|заглавие=Знакомьтесь, Erlang|издание=Системный администратор|ссылка=http://samag.ru/archive/article/2078 |год=2009|номер=8|issn=1813-5579|ref=Знакомьтесь, Erlang}}
* {{статья |автор=Дмитрий Васильев |заглавие=Знакомьтесь, Erlang |издание=Системный администратор |ссылка=http://samag.ru/archive/article/2078 |год=2009 |номер=8 |issn=1813-5579 |ref=Знакомьтесь, Erlang}}
* {{статья
* {{статья
|автор = Joe Armstrong
|автор = Joe Armstrong
Строка 848: Строка 869:
|том = 53
|том = 53
|номер = 9
|номер = 9
|страницы= 68—75
|pages = 68-75
|doi = 10.1145/1810891.1810910
|doi = 10.1145/1810891.1810910
}}
}}
* {{h|Armstrong, A History of Erlang|2007}}{{cite conference
* {{h|Armstrong, A History of Erlang|2007|{{cite conference
| author = Armstrong, Joe
| author = Armstrong, Joe
| year = 2007
| date = 2007-01
| month = January
| conference=HOPL III
| conference=HOPL III
| title = A History of Erlang
| title = A History of Erlang
| booktitle = Proceedings of the Third ACM SIGPLAN Conference on History of Programming Languages
| book-title = Proceedings of the Third ACM SIGPLAN Conference on History of Programming Languages
| url = http://doi.acm.org/10.1145/1238844.1238850
| url = http://doi.acm.org/10.1145/1238844.1238850
| accessdate = 2013-12-06
| accessdate = 2013-12-06
Строка 865: Строка 885:
| doi = 10.1145/1238844.1238850
| doi = 10.1145/1238844.1238850
| publisher = ACM
| publisher = ACM
}}
}}}}
* {{статья
* {{статья
|автор = Jim Larson
|автор = Jim Larson
Строка 874: Строка 894:
|год = 2008
|год = 2008
|номер = 5
|номер = 5
|страницы= 18—23
|pages = 18-23
|doi = 10.1.1.207.3752
|doi = 10.1.1.207.3752
|ref = Larson, Erlang for Concurrent Programming
|ref = Larson, Erlang for Concurrent Programming
Строка 887: Строка 907:
|номер = 8
|номер = 8
|том = 20
|том = 20
|страницы= 941—968
|pages = 941-968
|doi = 10.1002/cpe.1223
|doi = 10.1002/cpe.1223
|ref = Nyström, Trinder, King
|ref = Nyström, Trinder, King
Строка 921: Строка 941:
}}
}}
* {{статья
* {{статья
|автор =
|автор =
|заглавие = Начала работы с Erlang
|заглавие = Начала работы с Erlang
|ссылка = http://www.rsdn.ru/article/erlang/GettingStartedWithErlang.xml
|ссылка = http://www.rsdn.ru/article/erlang/GettingStartedWithErlang.xml
|оригинал = Getting Started With Erlang
|оригинал = Getting Started With Erlang
|издание = RSDN Magazine
|издание = RSDN Magazine
|год = 2006
|год = 2006
|номер = 3
|номер = 3
|issn = 0234-6621
|issn = 0234-6621
|archiveurl = http://www.webcitation.org/6LnmNSg40
|archiveurl = https://www.webcitation.org/6LnmNSg40?url=http://www.rsdn.ru/article/erlang/GettingStartedWithErlang.xml
|archivedate = 12-12-2013
|archivedate =
}}
}}
* {{h|Aronis, et al|2012}}{{cite conference
* {{h|Aronis, et al|2012|{{cite conference
| author = Aronis, Stavros and Papaspyrou, Nikolaos and Roukounaki, Katerina and Sagonas, Konstantinos and Tsiouris, Yiannis and Venetis, Ioannis E.
| author = Aronis, Stavros and Papaspyrou, Nikolaos and Roukounaki, Katerina and Sagonas, Konstantinos and Tsiouris, Yiannis and Venetis, Ioannis E.
| year = 2012
| year = 2012
| conference=Erlang '12
| conference=Erlang '12
| title = A Scalability Benchmark Suite for Erlang/OTP
| title = A Scalability Benchmark Suite for Erlang/OTP
| booktitle = Proceedings of the Eleventh ACM SIGPLAN Workshop on Erlang Workshop
| book-title = Proceedings of the Eleventh ACM SIGPLAN Workshop on Erlang Workshop
| url = http://doi.acm.org/10.1145/1238844.1238850
| url = http://doi.acm.org/10.1145/1238844.1238850
| accessdate = 2013-12-09
| accessdate = 2013-12-09
| pages = 33-42
| pages = 33—42
| id = 978-1-59593-766-7
| id = 978-1-59593-766-7
| location = Copenhagen, Denmark
| location = Copenhagen, Denmark
| doi = 10.1145/2364489.2364495
| doi = 10.1145/2364489.2364495
| publisher = ACM
| publisher = ACM
| isbn = 978-1-4503-1575-3,
| isbn = 978-1-4503-1575-3
}}
}}}}


== Ссылки ==
== Ссылки ==
* {{cite web|url=http://www.erlang.org/|title=Официальный сайт Open-source Erlang|lang=en}}
* {{cite web|url=http://www.erlang.org/|title=Официальный сайт Open-source Erlang|lang=en}}
* {{cite web|url=https://erlangcentral.org|title=Erlang Community Site|lang=en}}
* {{cite web|url=https://erlangcentral.org|title=Erlang Community Site|lang=en|access-date=2022-01-22|archive-date=2019-05-05|archive-url=https://web.archive.org/web/20190505130204/https://erlangcentral.org/|deadlink=yes}}
* {{cite web|url=http://erlanger.ru/|title=Erlang по-русски|description=новости на русском, проект по переводу документации на русский язык}}
* {{cite web|url=http://hlabs.spb.ru/development/erlang/|title=Язык программирования Erlang|author=Дмитрий Васильев}}
* {{cite web|url=http://hlabs.spb.ru/development/erlang/|title=Язык программирования Erlang|author=Дмитрий Васильев}}
* {{cite web|url=http://ko.com.ua/erlang_znakomstvo_ne_po_pravilam_43777|publisher=«Компьютерное Обозрение»|title=Erlang. Знакомство не по правилам|author=Андрей Зубинский|description=|date=20-07-2009}}
* {{cite web|url=http://ko.com.ua/erlang_znakomstvo_ne_po_pravilam_43777|publisher=«Компьютерное Обозрение»|title=Erlang. Знакомство не по правилам|author=Андрей Зубинский|description=|date=2009-07-20}}
* {{cite web|url=http://chimera.labs.oreilly.com/books/1234000000726|title=Études for Erlang|author=J. David Eisenberg|lang=en}}
* {{cite web|url=http://chimera.labs.oreilly.com/books/1234000000726|title=Études for Erlang|author=J. David Eisenberg|lang=en|accessdate=2013-12-05|archiveurl=https://web.archive.org/web/20131029012433/http://chimera.labs.oreilly.com/books/1234000000726|archivedate=2013-10-29|deadlink=yes}}
* {{cite web|url=http://www.tryerlang.org/|title=Try Erlang|description=онлайн-интерпретатор языка Erlang|lang=en}}
* {{cite web|url=http://www.tryerlang.org/|title=Try Erlang|description=онлайн-интерпретатор языка Erlang|lang=en}}
* {{cite web|url=http://www.erlang-factory.com/upload/presentations/536/ErlangConferencePresentation_2012.pdf|author=Gene I. Sher|title=Neuroevolution Through Erlang|publisher=Erlang Factory|description=Слайды с Erlang Factory в San Francisco, март 2012|lang=en}}
* {{cite web|url=http://www.erlang-factory.com/upload/presentations/536/ErlangConferencePresentation_2012.pdf|author=Gene I. Sher|title=Neuroevolution Through Erlang|publisher=Erlang Factory|description=Слайды с Erlang Factory в San Francisco, март 2012|lang=en}}


{{Языки программирования}}
{{Языки_программирования}}
{{Хорошая статья}}
{{Хорошая статья|Информатика}}


[[Категория:Функциональные языки программирования]]
[[Категория:Функциональные языки программирования]]
[[Категория:Декларативные языки программирования]]
[[Категория:Языки с динамической типизацией]]
[[Категория:Свободные компиляторы и интерпретаторы]]
[[Категория:Свободные компиляторы и интерпретаторы]]
[[Категория:Языки параллельного программирования]]
[[Категория:Языки параллельного программирования]]

Текущая версия от 19:40, 29 февраля 2024

Erlang
Изображение логотипа
Семантика мультипарадигмальный: параллельное, функциональное программирование
Класс языка мультипарадигмальный, язык параллельного программирования[вд], язык функционального программирования, декларативный язык программирования, язык программирования, открытое программное обеспечение, свободное программное обеспечение и умение
Появился в 1986[2]
Автор Джо Армстронг
Разработчик Джо Армстронг, Ericsson и Роберт Вирдинг[вд]
Расширение файлов .erl
Выпуск
Система типов сильная, динамическая
Испытал влияние ML, Пролог, Лисп, PLEX[вд], Smalltalk, Миранда, Ада, Модула-2 и CHILL
Лицензия Apache License 2.0[3]
Сайт erlang.org (англ.)
ОС кроссплатформенность[4]
Логотип Викисклада Медиафайлы на Викискладе

Erlang [ˈɜːlæŋ][5] — функциональный язык программирования с сильной динамической типизацией, предназначенный для создания распределённых вычислительных систем. Разработан и поддерживается компанией Ericsson. Язык включает в себя средства порождения параллельных легковесных процессов и их взаимодействия через обмен асинхронными сообщениями в соответствии с моделью акторов.

Erlang был целенаправленно разработан для применения в распределённых, отказоустойчивых, параллельных системах реального времени, для которых, кроме средств самого языка, имеется стандартная библиотека модулей и библиотека шаблонных решений (так называемых поведений) — фреймворк OTP (англ. Open Telecom Platform). Программа на Erlang транслируется в байт-код, исполняемый виртуальными машинами, находящимися на различных узлах распределённой вычислительной сети. Erlang-системы поддерживают горячую замену кода, что позволяет эксплуатировать оборудование безостановочно.

Свой синтаксис и некоторые концепции Erlang унаследовал от языка логического программирования Пролог[6]. Язык поддерживает многие типы данных, условные конструкции, сопоставление с образцом, обработку исключений, списковые включения и выражения битовых строк, функции (анонимные функции, функции высшего порядка, рекурсивные определения функций, оптимизацию хвостовой рекурсии), модули, приём и отправку сообщений между процессами. Препроцессор поддерживает работу с макросами и включение заголовочных файлов.

Популярность Erlang начала расти в связи с расширением его области применения (телекоммуникационные системы) на высоконагруженные параллельные распределённые системы, обслуживающие миллионы пользователей WWW, такие как чаты, системы управления содержимым, веб-серверы и распределённые, требующие масштабирования базы данных. Erlang применяется в нескольких NoSQL-базах данных высокой доступности[7].

Роберт Вирдинг (слева) и Джо Армстронг в 2013 году

В середине 1980-х годов в компьютерной лаборатории компании Ericsson исследовали применимость существовавших на тот момент языков программирования для программного обеспечения телекоммуникационных систем. Джо Армстронг, Роберт Вирдинг (Robert Virding) и Майк Вильямс (Mike Williams) под руководством Бьярне Деккера (Bjarne Däcker), написав прототипы программ на различных языках, пришли к выводу, что ни один из этих языков не имел полного набора возможностей, необходимых в области телекоммуникационных систем. В результате был создан новый язык программирования — Erlang[8]. Своё название язык, вероятно, получил в честь датского математика и инженера Агнера Эрланга, основателя научного направления по изучению сетевого трафика в телекоммуникационных системах. По другой версии, название языка изначально было сокращением от «Ericsson language»[9].

Влияние на Erlang оказали ML, Миранда, Ада, Модула-2, CHILL, Пролог. Кроме того, на способ обновления программного обеспечения повлиял Smalltalk и использованные Ericsson проприетарные языки EriPascal и PLEX[8].

Потребовалось четыре года развития языка и прототипирования с использованием виртуальной машины Пролога, после чего в 1991 году Майк Вильямс переписал виртуальную машину для Erlang на Си. В 1992 году Erlang был впервые использован в коммерческом проекте[8]. В 1995 году вышла новая версия Erlang, вобравшая накопившийся к тому моменту опыт использования языка. Язык был сочтён достаточно развитым для использования в других продуктах компании (решения для широкополосной связи, GPRS, ATM)[8].

В декабре 1995 года случилось событие, которое Джо Армстронг считает решающим для Erlang: проект AXE-N в Ellemtel по созданию нового маршрутизатора (как оборудования, так и системного программного обеспечения на C++) потерпел неудачу. В результате реорганизации проекта удалось, использовав разработанное оборудование и язык программирования Erlang, начать работы над ATM-маршрутизаторами серии AXD. Ресурсов лаборатории для такого проекта оказалось недостаточно, поэтому для работ по Erlang было создано производственное подразделение под названием OTP (Open Telecom Platform)[10]. В 1996 году увидел свет одноимённый фреймворк OTP[8].

Неожиданно[11], в 1998 году топ-менеджмент Ericsson решил не брать на себя обязательств по разработке и поддержке собственного языка программирования, сосредоточившись вместо этого на Java. Использование Erlang было запрещено в новых проектах Ericsson Radio AB в связи с реализацией плана по аутсорсингу программной технологии компании Rational Inc.[12][13] Это решение очень сильно повлияло на будущее Erlang: оно привело к открытию кода Erlang под открытой лицензией EPL (аналог Mozilla Public License)[14], а также послужило главной причиной начала распространения языка за пределами создавшей его компании. Основным возражением против открытия исходного кода являлось решение вопросов, касающихся патентов, но эти трудности были преодолены[15]. Вскоре многие из основных разработчиков покинули Ericsson, чтобы организовать собственный бизнес — Bluetail AB[15][12].

В начале 2000-х годов научные круги стали проявлять интерес к Erlang. С 2002 года стал проводиться ежегодный Erlang Workshop. Ericsson продолжал спонсирование проекта HiPE (от англ. High-Performance Erlang — высокопроизводительный Erlang)[16] уппсальского университета[Примечание 1]. Проект HiPE занимался эффективной реализацией языка и инструментами для проверки типов, а с 2001 года созданный в группе проекта компилятор в машинный код входит в поставку свободно распространяемой версии Erlang/OTP[10]. Работы, связанные с Erlang, ведут и другие высшие учебные заведения. Инструменты для рефакторинга созданы в Кентском университете в Великобритании и университете Ло́ранда Э́твёша в Венгрии, инструменты для различных видов тестирования — в Мадридском политехническом университете, техническом университете Чалмерса и Гётеборгском университете[17].

Когда системы с симметричной многопроцессорностью только начинали завоёвывать рынок серверов и настольных компьютеров, бросая вызов разработчикам программного обеспечения, уже в 2006 году первая версия Erlang с поддержкой SMP была выпущена совместными усилиями команды OTP из Ericsson и команды HiPE[16]. Вскоре после этого вышла первая почти за десятилетие крупная монография по Erlang: «Programming Erlang» Джо Армстронга[18], после чего многие разработчики «открыли» для себя Erlang/OTP[16], и язык стал набирать популярность[19].

Процесс развития языка включает в себя рассмотрение предложений по развитию — EEP (англ. Erlang Enhancement Proposal). Через эти предложения Erlang-сообщество вносит изменения в стандартную поставку Erlang[20]. С внесёнными предложениями можно ознакомиться на веб-странице erlang.org/eeps[21].

По свидетельству Майка Вильямса, Erlang задумывался для решения трёх проблем разработки распределённых систем мягкого реального времени с высокой степенью параллелизма: возможности быстрой и эффективной разработки ПО; получения системы, устойчивой к программным и аппаратным сбоям, и возможности обновления системы «на лету», без простоя оборудования[22].

По словам Вильямса, философия, которой придерживались разработчики Erlang, подходит и для разработки программного обеспечения на этом языке[23]:

  • Найдите наиболее подходящие методы. Проектируйте с использованием прототипов;
  • Одних идей мало: нужно уметь их реализовать и знать, что они работают;
  • Делайте ошибки в небольшом масштабе, а не в производственном проекте.

Большинство языков, созданных прежде Erlang, было разработано без предварительного нахождения своей области применения, тогда как Erlang был разработан специально на основе требований к распределённым, отказоустойчивым, параллельным системам реального времени. С развитием сети Интернет оказалось, что многие приложения имеют аналогичные требования[14], чем и объясняется растущий интерес к языку[24].

Высокая отказоустойчивость кроется в применении изолированных друг от друга легковесных процессов, связанных лишь механизмом обмена сообщениями и сигналами выхода. Принцип разработчиков на Erlang по отношению к обработке ошибочных ситуаций в процессах можно выразить в виде высказывания:

Позвольте приложению упасть, и пускай что-то другое имеет с этим дело.[25]

или сокращённо — «let it crash» («пусть падает»). Связано это с тем, что в Erlang-системе легко следить за завершением процесса, завершать процессы, связанные со сбойным, и запускать новые процессы[26].

Основные особенности

[править | править код]

Высокоуровневые конструкции

[править | править код]

Erlang является декларативным языком программирования, который скорее используется для описания того, что должно быть вычислено, нежели того,как. Например, определение функции, которое использует сопоставление с образцом для выбора одного из вариантов вычисления или извлечения элемента данных из составной структуры напоминает уравнение. Сопоставление с образцом распространено даже на битовые строки, что упрощает реализацию телекоммуникационных протоколов[14].

Функции являются объектами первого класса в Erlang. В языке также широко применяются характерные для функциональной парадигмы программирования списковые включения (генераторы списков)[27].

Параллельные вычисления

[править | править код]
Обмен сообщениями между процессами в Erlang

Отличительной особенностью языка является применение легковесных процессов в соответствии с моделью акторов. Такой подход позволяет выполнять одновременно сотни тысяч и даже миллионы таких процессов, каждый из которых может иметь скромные требования по памяти[28]. Процессы изолированы друг от друга и не имеют общего состояния, но между ними можно установить связь и получать сообщения об их состоянии. Для взаимодействия процессов используется асинхронный обмен сообщениями. Каждый процесс имеет свою очередь сообщений, обработка которой использует сопоставление с образцом. Процесс, отправивший сообщение, не получает уведомления о доставке, даже если идентификатор процесса-получателя недействителен или получатель игнорирует сообщение. Таким образом, ответственность за правильно организованное взаимодействие между процессами лежит на разработчике[29].

Например, при реализации на Erlang сетевого чата структура программы может напрямую отражать одновременность действий пользователей по обмену сообщениями путём запуска новых процессов. Эффективность передачи сообщений сохраняется и при увеличении числа процессов, а требования к памяти минимизируются за счёт того, что легковесными процессами управляет виртуальная машина, а не средства нижележащей операционной системы[30].

Распределённые вычисления

[править | править код]

Erlang с самого начала проектировался для распределённых вычислений и масштабируемости. Распределение вычислений встроено в синтаксис и семантику языка, поэтому построение системы можно вести, абстрагируясь от конкретного места вычислений. В стандартной поставке Erlang может наладить связь процессов по протоколу TCP/IP независимо от поддерживаемых им нижележащих платформ (операционных систем)[31].

Работающий экземпляр среды выполнения Erlang (англ. Erlang runtime system) называется узлом (англ. node). Программы, написанные на Erlang, способны работать на нескольких узлах. Узлами могут быть процессоры, многие ядра одного процессора, и даже целый кластер машин. Узел имеет имя и «знает» о существовании других узлов на данной машине или в сети. Создание и взаимодействие процессов разных узлов не отличается от организации взаимодействия процессов внутри узла. Для создания процесса на другом узле процессу достаточно знать его имя и, без особых на то оснований, он может не интересоваться физическим расположением взаимодействующего с ним процесса. Синтаксис отправки сообщения процессу на своём узле и удалённом — один и тот же[31].

Благодаря встроенным в язык возможностям распределённых вычислений объединение в кластер, балансировка нагрузки, добавление узлов и серверов, повышение надёжности вызывают лишь небольшие затраты на дополнительный код. По умолчанию узлы спроектированы для работы внутри обособленного сегмента сети (DMZ), но, если необходимо, коммуникация между узлами может происходить с применением защищённого криптографическими методами протокола SSL[31].

Мягкое реальное время

[править | править код]

Программы на высокоуровневом языке Erlang могут быть использованы в системах мягкого реального времени (которое иногда переводят как «псевдореальное» или «квазиреальное»[32]). Автоматизированное управление памятью и сборка мусора действуют в рамках одного процесса, что даёт возможность создавать системы с миллисекундным временем отклика (даже несмотря на необходимость сборки мусора), не испытывающие ухудшения пропускной способности при высокой нагрузке[33].

Горячая замена кода

[править | править код]

Для систем, которые не могут быть остановлены для обновления кода, Erlang предлагает горячую замену кода (англ. hot code upgrade). При этом в приложении могут одновременно работать старая и новая версии кода. Таким способом программное обеспечение на Erlang может быть модернизировано без простоев, а выявленные ошибки исправлены[9][34].

Описание языка

[править | править код]

Типы данных

[править | править код]

Типизация в Erlang является сильной и динамической. Динамическая типизация была выбрана для языка Erlang по причине того, что первые разработчики были больше с ней знакомы[35]. По мнению Джо Армстронга, статическая типизация потребовала бы очень больших трудозатрат, в частности, реализовать систему горячей дозагрузки кода было бы крайне затруднительно[36]. Такая типизация, при которой возможные ошибки типов выявляются только во время выполнения, тем не менее, не помешала создавать системы с очень высоким уровнем доступности[35]. Данные в Erlang являются неизменяемыми: операции не переписывают старые значения, находящиеся в памяти. Если необходимо, модули на Erlang можно снабдить описаниями и определениями новых типов (не влияющими на компиляцию программы) для автоматической проверки типов с помощью утилиты Dialyzer[37].

В Erlang есть два типа числовых литералов: целые и с плавающей запятой, например: 125, 4.5e-20. Кроме обычной нотации, числа можно задавать через символ ASCII (например, $B означает 66) или вместе с указанием системы счисления с основанием от 2 до 36 (в старых версиях — до 16), например: 16#3f, 2#1010. В Erlang применяются целые числа произвольной точности и действительные числа двойной точности (64 бита), в стандарте IEEE 754—1985[38].

Для работы с числами можно использовать модуль math, который содержит обычный набор математических функций и функцию math:pi/0, возвращающую число [39]. Пример вычислений в интерактивной оболочке:

Erlang R15B01 (erts-5.9.1) [source] [64-bit] [smp:4:4] [async-threads:0] [kernel-poll:false]

Eshell V5.9.1 (abort with ^G)
1> 123/23 + 12*(2+3).
65.34782608695652
2> math:cos(math:pi()).
-1.0
3> random:uniform(10).
5

Атом — константа с именем, которая должна быть заключена в одинарные кавычки, если не начинается со строчной буквы или содержит знаки, кроме букв, цифр, подчёркивания, точки и символа @. Понятие атома заимствовано из Пролога и его можно считать аналогом перечислений (enum) в других языках программирования (без необходимости предварительной декларации)[40]. Атомы используются почти исключительно в сравнениях, имеющих в Erlang очень эффективную реализацию[41]. Кроме того, некоторые атомы имеют определённый смысл в возвращаемых значениях и описании исключений. К ним относятся: error, ignore, noreply, ok, reply, stop, undefined[42].

Битовые строки и бинарные данные

[править | править код]

Битовая строка используется для хранения в памяти нетипизированных данных. Строки, состоящие из целого количества октетов, называются бинарными (или двоичными) данными (англ. binaries). Синтаксис описания битовой строки довольно гибок, так как описывает значения битов отдельных диапазонов и может быть снабжён модификатором типа[43]. Несколько примеров в интерактивной командной оболочке:

1> <<23,89,120>>.
<<23,89,120>>
2> <<"ABC">>.
<<65,66,67>>
3> <<10,17,42:16>>.
<<10,17,0,42>>
4> <<$a, $b, $c>>. 
<<"abc">> 
5> <<1024/utf8>>.
<<208,128>>

Выражения битовых строк (англ. bitstring comprehension) аналогичны списковым включениям, но работают над битовыми строками[44]:

1> << <<bnot(X):1>> || <<X:1>> <= <<2#111011:6>> >>.
<<4:6>>

В этом примере переменная X последовательно получает биты числа 2#111011, которые затем инвертируются операцией битового отрицания bnot (от англ. binary NOT), в результате чего получается число 4.

Кортеж (англ. tuple) — составной тип данных с фиксированным количеством элементов. При доступе к элементам кортежа с помощью встроенных функций нумерация элементов начинается с единицы, а не с нуля. Первый элемент кортежа принято использовать для указания роли кортежа в программе. Если первый элемент — атом, его называют тегом (англ. tag — «метка»). В Erlang принято строить различные типы данных на основе кортежей с тегами, что облегчает отладку программы и считается хорошим стилем программирования[45].

Для работы с кортежами есть несколько встроенных функций, например[45]:

1> tuple_size({a, 1, "777"}).
3
2> element(1, {b, 2, 3, 4}).
b
3> setelement(1, {c, 5}, d). 
{d,5}

Список (англ. list) — составной тип данных, содержащий переменное число элементов. Для манипуляции со списками можно применять функции модуля lists стандартной библиотеки[46]. Формально список определяется как имеющий голову (англ. head) и хвост (англ. tail), что выражается синтаксически в виде [HEAD|TAIL], где хвост обычно является списком (возможно, пустым). Пустой список обозначается [][47].

Списки можно записывать и более привычным способом. Следующие записи эквивалентны:

1> [a|[b|[c|[]]]].
[a,b,c]

Для работы со списками можно применять списковые включения[48] (генераторы списков), например:

1> [ X / 2 || X <- [1,2,3,4]].
[0.5,1.0,1.5,2.0]

Модуль lists стандартной библиотеки содержит функции для обработки списков (и строк, так как в Erlang строка является списком)[49], такие как нахождение максимума, сортировка, изменение порядка элементов на противоположный, суммирование элементов и т. п. В следующем примере два списка склеиваются операцией конкатенации, а затем разбиваются на две части функцией lists:split/2:

1> lists:split(2, [l,2,3]++[4,5,6]).
{[l,2],[3,4,5,6]}

В модуле lists имеется также набор функций высшего порядка, таких как lists:all/2, lists:any/2, lists:dropwhile/2, lists:filter/2, lists:foldl/3, lists:foldr/3, lists:map/2, lists:foreach/2. Следующий пример иллюстрирует работу функции lists:foldr (англ. fold — свернуть, «r» от англ. right — правая) для свёртки списка, первым параметром которой должна быть функция:

1> D = fun(V, A) -> V / A end. % функция D - деление V на A
#Fun<erl_eval.12.82930912>
2> lists:foldr(D, 1, [1, 2, 4, 8]). 
0.25
3> 1/(2/(4/(8/1))). 
0.25

Результат выполнения свёртки справа налево (в строке 2) тождественен цепочечному делению (строка 3). Второй параметр foldr даёт начальное значение для так называемого аккумулятора. Для каждого элемента списка (справа налево) к элементу и аккумулятору применяется функция, заданная первым аргументом foldr, а значение записывается в аккумулятор. По исчерпанию списка функция возвращает значение аккумулятора[50]. Функция является достаточно мощным средством, если учесть, что аккумулятор может быть списком или кортежем[51].

В Erlang нет самостоятельного типа для строк: внутренне строки представляются списками. Синтаксически строку можно задать кавычками. Так, "Привет!" равносилен (в подходящей кодировке) списку [1055,1088,1080,1074,1077,1090,33]. Erlang поддерживает Unicode как в строке, так и в записи отдельного знака (через $)[52].

Атомы и строки внешне достаточно похожи, но имеют совершенно различные реализации. Тогда как атомы можно только сравнивать, строки поддерживают многие другие операции, для них есть множество функций в модулях lists и string. Строка может выполнять функции атома, но память, занимаемая строкой пропорциональна её длине, тогда как атомы хранятся в системной таблице и на каждое использование атома в программе приходится лишь пара байтов, вне зависимости от длины атома. Сравнение двух атомов — это сравнение двух внутренних идентификаторов, выполняемое за одну операцию, тогда как сравнение строк предполагает поэлементный проход элементов строк[53].

Логические значения

[править | править код]

Для значений истина и ложь в Erlang применяются атомы true (истина) и false (ложь), которые и используются операциями сравнения, логическими операциями, встроенными функциями[54]. Пример:

1> 2 < 3. 
true
2> is_boolean(125).
false

Функциональный объект (Fun)

[править | править код]

Fun-выражение позволяет создать анонимную функцию, например, для передачи в качестве параметра другим функциям. С помощью fun можно также получить функциональный объект для функции из модуля[55]. Примеры:

1> lists:map(fun(X) -> X + 1 end, [1, 2, 3]). 
[2,3,4]
2> Belongs = fun lists:member/2.
#Fun<lists.member.2>
3> Belongs(a, [a, b]). 
true

Чтобы помечать отдельные элементы кортежей и избежать ошибок при написании программы, в Erlang был внесён синтаксис записей (англ. record). Для работы с записями, необходимо в начале дать описание записи директивой -record, например, для записи user описание может быть следующим[56]:

-record(user, {login="anon", password, nick}).

Из этого описания компилятор узнаёт, что имеются в виду кортежи из четырёх элементов, в которых элементы со второго по четвёртый соответствуют полям login, password, nick (порядок важен) записи с именем user (определяется атомом в первом элементе кортежа). Значением по умолчанию для поля login является строка "anon". Если значение по умолчанию не указано явно, подразумевается атом undefined.

Создание записей и извлечение элементов записи всегда требует явного указания имени записи[56]:

R0 = #user{} % все поля получают значения по умолчанию
R1 = #user{login="user1", password="secret", nick="john"} % все поля получили значения

Синтаксис доступа к значениям полей записи: R1#user.login, R0#user.nick[56].

Ассоциативный массив

[править | править код]

Ассоциативный массив (словарь) хранит пары вида «(ключ, значение)». В качестве как ключа, так и значения, может выступать любой терм Erlang.

Map = #{a => 2, b => 3, c=> 4, "a" => 1, "b" => 2, "hi" => 42},
Key = "hi",
maps:find(Key,Map).
{ok,42}

Другие типы

[править | править код]

В языке Erlang имеются и другие типы данных. Тип ссылка (англ. reference) является практически уникальной в среде времени выполнения Erlang[57]. Ссылка создаётся вызовом функции make_ref/0 и может повториться через 282 вызовов этой функции[58]. Ссылки можно сравнивать на равенство, а применяются они для одноразовых пометок или «волшебного печенья»[59].

Идентификатор порта (англ. port identifier) определяет порт для связи с внешним по отношению к Erlang-системе миром. Порт позволяет создавшему его процессу-владельцу (так называемому присоединённому процессу) обмениваться бинарными сообщениями со сторонними программами и ОС способом, принятым в данной операционной системе[59][60][41].

Идентификатор процесса (англ. Pid), как и следует из его названия, идентифицирует процесс, порождаемый различными функциями spawn. Идентификатор можно считать уникальным во время работы Erlang-системы, но в долго работающих системах могут всё-таки быть использованы повторно, что обычно не является проблемой на практике[59].

Встроенные функции для работы с типами

[править | править код]

Для преобразования типов используются встроенные функции (BIF, от англ. builtin function) вида x_to_y («из x в y»), а для проверки принадлежности значения тому или иному типу — функции вида is_x («является x»):

1> atom_to_list(hello).
"hello"
2> list_to_binary("world").
<<"world">>
3> tuple_to_list({1,2,3,4}).
[1,2,3,4]
1> is_integer(3).
true
2> is_tuple("abc").
false
3> is_integer(3.0).
false

Арифметические операции

[править | править код]

Erlang предоставляет наиболее распространённые арифметические операции для целых чисел и чисел с плавающей запятой:

Обозначение Выполняемая операция Пример Результат примера
+ Унарный плюс +3 3
- Унарный минус -3 -3
+ Сложение 2+3 5
- Вычитание 7-3 4
* Умножение 1.2*0.4 0.48
/ Деление 5 / 3 1.6666666666666667
div Целочисленное деление 5 div 3 1
rem Нахождение остатка от деления 5 rem 3 2

Все эти операции левоассоциативны. Унарные операции имеют наивысший приоритет, затем следует умножение и деление, наименьший приоритет у сложения и вычитания. При необходимости целое может приводиться к типу с плавающей запятой[61].

Битовые операции

[править | править код]

Битовые операции работают над целыми числами и дают в результате целое число[62].

Обозначение Выполняемая операция Пример Результат примера
bnot Побитовое отрицание bnot (2#1000) -9
band Побитовое И 2 band 3 2
bor Побитовое ИЛИ 1 bor 2 3
bxor Побитовое исключающее ИЛИ 5 bxor 3 6
bsr Побитовый сдвиг вправо 32 bsr 2 8
bsl Побитовый сдвиг влево 1 bsl 5 32

Логические операции

[править | править код]

Логические операции работают над логическими значениями true (истина) и false (ложь), получаемыми в результате сравнений и применения функций проверки типа[63].

Обозначение Выполняемая операция Пример Результат примера
not Отрицание (НЕ) not true false
and Конъюнкция (И) true and (1 < 5) true
andalso Аналогично and, но не вычисляет второй операнд, если первый false false andalso (1 < 5) false
or Дизъюнкция (ИЛИ) is_atom("1") or is_atom(1) false
orelse Аналогично or, но не вычисляет второй операнд, если первый true true orelse (1 < 5) true
xor Исключающее ИЛИ true xor true false

Операции сравнения

[править | править код]

Операции сравнения получают два операнда, а результатом операции является логическое значение true или false. В Erlang есть следующие операции: == (равно), /= (не равно), =< (меньше или равно), < (меньше), > (больше), >= (больше или равно), а также сравнения, которые работают без приведения к одному типу: =/= (не равно в точности) и =:= (равно в точности).

Можно сравнивать и значения разных типов, но они считаются в Erlang упорядоченными следующим образом[64]:

число < атом < ссылка < функция < порт < идентификатор процесса < кортеж < список < бинарные данные

Списки считаются упорядоченными в лексикографическом порядке, а кортежи сравниваются по длине, и только затем в лексикографическом порядке[64].

Переменные

[править | править код]

Переменные служат для хранения значений простых и составных типов. Имя переменной начинается с прописной буквы (в специальных случаях — с подчёркивания) и может содержать буквы, цифры, подчёркивания. Значение можно присвоить переменной лишь один раз — это свойство языка программирования называется единичным присваиванием (англ. single assignment)[65]. К достоинствам единичного присваивания можно отнести устранение необходимости в блокировках, а также упрощение отладки программы[66].

Передача параметров в функцию происходит по значению, поэтому все они вычисляются перед вызовом функции[65].

Область видимости переменной распространяется от момента её появления в заголовочной части описания функции или присваивания до конца части описания функции. Пример[67]:

binomial(X) -> Y = X*X, X + Y.
prod([1|T]) -> prod(T);
prod([Y|T]) -> Y * prod(T);
prod([]) -> 1.

В этом примере область видимости X — всё описание функции binomial/1, а Y — от присваивания до конца описания. Переменная Y во второй части (клоза) описания функции prod/1 не имеет отношения к переменной Y из binomial/1: её область видимости распространяется до конца этого клоза.

При выходе вычислений за пределы области видимости переменной память, занятая её содержимым, может быть освобождена в процессе сборки мусора, если значение переменной не используется в другой части программы[68].

Сопоставление с образцом

[править | править код]

Сопоставление с образцом используется в Erlang для присваивания (в том числе, при работе с параметрами функций), управления потоком выполнения программы, извлечения значений составных типов, выбора сообщения из очереди. В левой части сравнения (или в заголовке функции) могут находиться связанные (уже имеющие значение) и несвязанные (получающие значение) переменные, а также литералы (атомы, числа, строки). В результате исполнения сравнение может оказаться успешным (в этом случае переменные связываются со значениями) и неуспешным — переменные остаются несвязанными. В образце могут быть переменные, значение которых для образца безразлично: их имена записываются начинающимися с подчёркивания[69]. Переменная с именем _ (подчёркивание) сопоставляется с любым значением, но при этом не происходит связывания. Такую переменную можно применять много раз.

Программы на Erlang состоят из функций, которые вызывают друг друга. Количество параметров функции называется арностью. При вызове функции заголовочные части описания функции сопоставляются с образцом. В случае совпадения параметров вызова, формальные параметры связываются с фактическими и исполняется соответствующая часть тела функции[70]. Запись варианта вычисления функции для некоторого образца может называется клозом от англ. clause, а определение функции — это набор из одного или более клозов[71].

Для уточнения сопоставления с образцом в функциях можно использовать охранные выражения, которые следуют после ключевого слова when[72]. В примере ниже определена функция вычисления знака числа, которая рассчитывается в зависимости от сравнения параметра с нулём:

sign(X) when X > 0 -> 1;
sign(X) when X == 0 -> 0;
sign(X) when X < 0 -> -1.

Клозы Erlang перебирает в том порядке, в котором они записаны, пока не будет найден подходящий заголовок[73]. В охранных выражениях можно использовать только ограниченный набор встроенных функций, так как эти функции не должны иметь побочных эффектов.

Разумеется, функции Erlang поддерживают рекурсивные вызовы. В случае, когда определение функции оканчивается рекурсивным вызовом (хвостовая рекурсия), Erlang использует оптимизацию: стек вызовов не применяется[74].

Как параметром, так и результатом функции может быть другая функция. В следующем примере функция одного аргумента возвращает функцию для прибавления аргумента[75]:

1> Plus = fun (X) -> fun(Y) -> X+Y end end. % Определение функции, возвращающей функцию
#Fun<erl_eval.6.82930912>
2> Plus(2).                                 % Функция возвращает Fun-объект 
#Fun<erl_eval.6.82930912>
3> Plus(2)(3).                              % Такой синтаксис не работает
* 1: syntax error before: '('
4> (Plus(2))(3).                            % Дополнительные скобки позволяют добиться требуемого результата
5
5> Plus2 = Plus(2), Plus2(3).               % То же самое с использованием дополнительной переменной
5

Вычисление факториала на Erlang:

-module(fact).
-export([fac/1]).

fac(0) -> 1;
fac(N) when N > 0, is_integer(N) -> N * fac(N-1).

Алгоритм сортировки, напоминающий быструю сортировку[34]:

-module(qsort).
-export([qsort/1]).

qsort([]) -> []; % Тривиальный случай пустого списка
qsort([Pivot|Rest]) ->
    % Конкатенация списка элементов до Pivot, списка из одного элемента Pivot и после Pivot
    qsort([Front || Front <- Rest, Front < Pivot])
    ++ [Pivot] ++
    qsort([Back || Back <- Rest, Back >= Pivot]).

В этом примере функция qsort вызывается рекурсивно до исчерпания всех элементов. Выражение [Front || Front <- Rest, Front < Pivot] собирает список Front из элементов Rest таких, что элемент Front меньше Pivot. Оператор ++ склеивает списки.

Условные выражения

[править | править код]

Кроме выбора описания в определении функции, в Erlang есть и другие условные выражения: case-выражения (выражение выбора) и if-выражения. Выражение выбора позволяет организовать сопоставление с образцом внутри функции и обычно имеет следующий синтаксис:

case выражение-выбора of
  образец1 when охрана1 -> выражение11, выражение12, ...;
  образец2 when охрана2 -> выражение21, выражение22, ...;
  ...
  образецN when охранаN -> выражениеN1, выражениеN2, ...
end

Это выражение всегда возвращает значение, соответствующее последнему вычисленному выражению в строке с подошедшим образцом. Это возвращаемое значение может служить возвращаемым значением функции, а может быть присвоено переменной[76]. Как и в заголовочной части функции, после образца может следовать охранное выражение.

Упрощённым вариантом case-выражения является if-выражение:

if
  охрана1 -> выражение11, выражение12, ...;
  охрана2 -> выражение21, выражение22, ...;
  ...
  охранаN -> выражениеN1, выражениеN2, ...
end

Здесь охранаi — охранное выражение. Первое истинное охранное выражение вызывает выполнение соответствующих выражений, последнее из которых и является значением всего if-выражение[77]. Следует заметить, что и здесь в охранном выражении можно применять только ограниченный набор операций и встроенных функций.

Запятые в охранном выражении работают как операция and, например[78]:

if
  X =< 0 -> 'меньше или равно нулю';
  X > 0, X < 10 -> 'больше нуля и меньше десяти';
  X >= 10 -> 'больше или равно десяти';
end

Компилятор Erlang следит за безопасностью связывания переменных внутри условных выражений, как видно из следующего примера модуля:

-module(badexample).
-export([broken_if/1]).
broken_if(X) ->
  if
    X < 0 -> Z = -1;
    X >= 0 -> Y = 1
  end,
  Y * Z.

При попытке откомпилировать модуль возникают сообщения об ошибках, так как в таком коде одна из переменных не связывается со значением:

1> c(badexample).
badexample.erl:8: variable 'Y' unsafe in 'if' (line 4)
badexample.erl:8: variable 'Z' unsafe in 'if' (line 4)
error

Правильным было бы определить все используемые далее по коду переменные во всех ветвях if-выражения[79].

Препроцессор и макросы

[править | править код]

Препроцессор Erlang (EPP) позволяет вкладывать файлы с исходным кодом один в другой, определять макросы и осуществлять простые и параметризованные макроподстановки[80]. Макрос определяется с помощью директивы -define, а макроподстановка осуществляется указанием имени макроса и возможных параметров после вопросительного знака (?). Следующий пример показывает определение и применение параметризованного макроса:

-define(ZERO(X),X == 0)
is_zero(T) when ?ZERO(X) -> true;
is_zero(T) -> false.

Имя макроса обычно пишется прописными буквами. Определение макроса должно содержать лексемы Erlang целиком (например, попытка задать часть имени переменной с помощью макроса вызовет синтаксическую ошибку). Макросы могут использоваться для повышения удобочитаемости кода в охранных выражениях, для операторов отладки и т. п.[81] Препроцессор имеет несколько предопределённых макросов, которые нельзя переопределить: ?MODULE, ?MODULE_STRING, ?FILE, ?LINE, ?MACHINE[82].

Заголовочный файл (расширение .hrl) с определениями макросов и записей можно включить при помощи директивы -include[83].

Обработка ошибок

[править | править код]

Для обработки исключительных ситуаций в Erlang можно применять конструкцию try-catch, в общем случае записываемую в следующем виде[84]:

try вычисляемое-выражение of
  образец1 when охрана1 -> выражение1;
  образец2 when охрана2 -> выражение2;
  ...
  образецN when охранаN -> выражениеN
catch
  класс1:образецИскл1 when охранаИскл1 -> выражениеИскл1;
  ...
  классM:образецИсклM when охранаИсклM -> выражениеИсклM;
end

Как и в случае case-выражения, вычисляемое выражение сопоставляется с образцом (части между of и catch) для получения результата[Примечание 2][85]. После ключевого слова catch следуют части обработки исключений, в которых в дополнение к образцам исключений могут быть указаны классы исключений (перед двоеточием): error, throw и exit. Подчёркивание может использоваться как в образце, так и в классе исключения[86]. Следующий простой пример иллюстрирует перехват ошибки класса error при вычислении квадратного корня:

1> try math:sqrt(-1) catch error:Error -> {error, Error} end.
{error, badarith}
2> try math:sqrt(4) catch error:Error -> {error, Error} end.
2.0

Для создания исключений, определённых пользователем, используется функция throw/1, которая принимает кортеж с более детальным описанием возникшей ошибки[87] и генерирует исключение класса throw. Использование этой функции нежелательно из-за ухудшения удобочитаемости кода программы, но может потребоваться в некоторых случаях при работе с вложенными структурами данных, например, при разборе XML[86]. Исключения класса exit возникают в результате вызова встроенной функции exit/1 или сигнала выхода[86].

До разработки Ричардом Карлссоном (Richard Carlsson) из команды проекта HiPE описанного выше нового механизма обработки исключений (появился в версии R10B) в Erlang использовались catch-выражения[88].

Код программы на Erlang можно разбить на отдельные модули. Модуль — имя для набора функций, организованных в одном файле. Имя модуля должно совпадать с именем файла (если отбросить расширение)[89]. Модуль можно откомпилировать в байт-код как из командной строки операционной системы, так и из командной оболочки Erlang[90]. В файле модуля можно записать объявления функций и директивы (иногда называются атрибутами)[91]. Обязательным атрибутом является только -module(атом_имени_модуля). Другой часто используемый атрибут — -export — применяется для указания списка экспортируемых функций, то есть функций, которые можно использовать за пределами модуля.

Функции в Erlang однозначно определяются модулем, именем и арностью. Например, math:cos/1 соответствует функции cos из модуля math, принимающей один аргумент. Вызвать функцию можно так: math:cos(1.2)[89].

Исходный текст модуля компилируется в BEAM-файл — файл, содержащий байт-код виртуальной машины BEAM (англ. Bogdan’s/Björn's Erlang Abstract Machine[90]). В свою очередь, ERTS (англ. Erlang Runtime System — система времени выполнения Erlang) выполняет этот код[55].

Основной абстракцией параллельного программирования в Erlang является процесс. Процессы могут порождать другие процессы, выполняться одновременно, обмениваться сообщениями, реагировать на завершение друг друга.

Создание процессов

[править | править код]

Для создания нового процесса служит несколько встроенных функций (spawn и её аналоги)[92]. Функции возвращают идентификатор процесса, который может использоваться, например, для отправки сообщений вновь созданному процессу. В интерактивной консоли erl можно получить список процессов и другую информацию посредством вызова функций processes(). и i(). соответственно[93].

Отправка и приём сообщений

[править | править код]

Как и язык Оккам, Erlang использует для отправки сообщения синтаксис с восклицательным знаком: ИдПроцесса ! Сообщение. Приём сообщения — то есть извлечение его из очереди («почтового ящика») процесса — выполняется с помощью receive-выражений, обычно записываемых следующим образом[94]:

receive
  образец1 when охрана1 -> выражение11, выражение12, ...;
  образец2 when охрана2 -> выражение21, выражение22, ...;
  ...
  образецN when охранаN -> выражениеN1, выражениеN2, ...;
  НесвязаннаяПеременнаяДляОстальныхСообщений -> выражение1, выражение2, ...
end

Встретив такое выражение, интерпретатор последовательно просматривает сообщения из очереди. Каждое сообщение интерпретатор сопоставляет с образцом и, если оно удовлетворяет образцу, вычисляются соответствующие выражения. Когда все сообщения перебраны, и подходящего не оказалось, процесс блокируется в ожидании новых сообщений, после чего перебор очереди повторяется. Если в receive-выражении отсутствует образец, которому удовлетворяет любое сообщение, такое выражение называется выборочным receive-выражением[93].

Обработка ошибок и завершение процессов

[править | править код]

Процесс можно связать с другим, в результате чего между процессами устанавливается двунаправленное соединение (англ. link). В случае, если один из процессов завершается ненормально, всем связанным с ним процессам передаётся сигнал выхода (англ. exit signal). Процессы, получившие сигнал, завершаются, распространяя сигнал дальше[95][96]. Сигнал выхода является кортежем, элементами которого являются атом 'EXIT' (выход), идентификатор завершившегося процесса и причину завершения процесса. Причина завершения передаётся по цепочке завершающихся процессов[97].

Процесс может осуществить перехват ошибки (англ. trapping errors), если у него установлен флаг перехвата выхода[Примечание 3]. Такой процесс получает сигналы выхода связанных с ним процессов в виде обычных сообщений с той же структурой кортежа. Перехваченный сигнала выхода более не передаётся связанным с процессом-перехватчиком процессам[98]. Сигнал выхода с причиной — атомом normal (нормальное завершение процесса) не вызывает завершения связанного процесса. Если же причина — атом kill, процесс завершается безусловно (независимо от флага перехвата выхода), а связанным с ним процессам в качестве причины отправляется атом killed, что даёт им возможность среагировать[99].

В Erlang есть возможность установить и однонаправленное соединение. При завершении наблюдаемого процесса процесс-наблюдатель получает сообщение с указанием причины завершения[100].

Процесс может остановить сам себя или другой процесс, вызвав функцию exit[101].

Ввод-вывод

[править | править код]

В планировщике процессов Erlang-системы проблема ввода-вывода, присущая многим другим языкам параллельного программирования, решена достаточно элегантно. Управление вводом-выводом, интегрированное с планировщиком, уже на самом нижнем уровне осуществляется на основе событий, что позволяет программе обрабатывать входящие и исходящие данные без излишних блокировок. Такой подход требует меньшего числа установки и разрыва соединений, а также убирает необходимость в блокировках и переключениях контекста. К сожалению, такой достаточно эффективный способ более сложен для понимания программистами, и находит применение в основном в системах с явными требования по высокой доступности и низкому времени отклика. Реализация событийно-ориентированного ввода-вывода встроена в Erlang-систему, что является ещё одним преимуществом при проектировании параллельных приложений[102].

Стандартная библиотека содержит модуль io с функциями ввода-вывода. Такие функции содержат побочные эффекты, заключающиеся в появлении выведенной информации на консоли или записывании данных в файл на диске. Например, функция io:format для форматированного вывода выводит строку с подстановкой параметров, возвращая в случае успеха атом ok[103]:

1> io:format("Пример вывода: ~p~n", [1]). 
Пример вывода: 1
ok

Функции модуля io включают в себя стандартный серверный интерфейс ввода-вывода. Протокол ввода-вывода Erlang (англ. The Erlang I/O-protocol) детально определяет связь клиента и сервера. Под сервером ввода-вывода понимается процесс, который обрабатывает запросы и выполняет запрошенные команды, например, на устройстве ввода-вывода. Клиентом является любой Erlang-процесс, которому требуется работать с устройством[104][105].

Библиотеки

[править | править код]

Стандартная библиотека модулей

[править | править код]

Согласно официальной документации, стандартная библиотека модулей STDLIB[106] является обязательной для включения в минимальную систему Erlang/OTP[107] наряду с ядром Erlang. В библиотеку входят модули, предоставляющие разнообразные функции для работы со встроенными типами и другими структурами данных, ввода-вывода, обращения к среде окружения, для работы с файловой системой, процессами и т. п.

Модуль array определяет (функциональный) абстрактный тип данных для динамического массива и имеет функции, позволяющие извлекать и обновлять элементы массива, определять рекурсивные функции для работы с массивами. Модуль string расширяет возможности модуля lists функциями для работы конкретно со списками символов, какими являются строки в Erlang. Модуль dict (от англ. dictionary — словарь) содержит функции для ассоциативного массива, позволяющие хранить, извлекать и удалять значения по ключу, соединять массивы и производить итерации по элементам. Математические функции можно найти в модуле math, а функции для генерации псевдослучайных чисел содержатся в модуле random. Модуль calendar предоставляет функции для григорианского календаря: запросы текущей даты, преобразования единиц измерения и интервалов времени, а модуль timer содержит функции перевода интервалов времени к миллисекундам, запуска событий по таймеру и другие, связанные со временем, функции. Модуль erlang содержит все встроенные функции Erlang, как общие, так и относящиеся к виртуальной машине. Модуль file даёт доступ к функциям файловой системы, таким как открытие, чтение, запись, удаление файлов, а модуль filename позволяет писать функции для манипуляции с именами и путями к файлам, абстрагируясь от конкретной операционной системы. Модуль io предоставляет функции ввода-вывода. Кроме этих наиболее важных модулей, стандартная библиотека содержит и многие другие, с которыми можно познакомиться по документации[108].

Таблицы ETS и DETS

[править | править код]

Для организации коллекций в оперативной памяти Erlang предлагает модуль ets (ETS, англ. Erlang Term Storage — «хранилище термов Erlang»[Примечание 4]). ETS может хранить четыре вида коллекций: множество (англ. set), упорядоченное множество (англ. ordered set), мультимножество (англ. bag), мультимножество с повторениями (англ. duplicate bag)[109]. Доступ к элементам коллекций происходит по ключевому полю кортежа (ключи могут быть любых типов). Упорядоченные множества реализованы в виде бинарных сбалансированных АВЛ-деревьев, а остальные коллекции — с использованием хеш-таблиц[110].

DETS-таблицы дополняют функциональность ETS-таблиц (за исключением упорядоченных множеств), позволяя сохранять данные в файлах[111].

Фреймворк OTP

[править | править код]
Дерево процессов

OTP (англ. Open Telecom Platform) является хорошо отлаженным набором полезных поведений (англ. behaviours) процессов и используется для создания серверных приложений. OTP формализует действия процессов и позволяет строить на их основе OTP-приложения (не следует путать с приложением — готовым программным продуктом). В модулях ОТР определены общие, стандартизированные шаблоны для конструирования параллельных приложений[112]. Наиболее популярными поведениями являются обобщённый сервер и наблюдатель (англ. supervisor), но имеются и другие: конечный автомат, обработчик событий[113]. OTP содержит и другое связующее программное обеспечение (англ. middleware), например, СУБД Mnesia.

OTP-поведения делятся на рабочие процессы (англ. worker processes), выполняющие собственно обработку запросов, и процессов-наблюдателей (англ. supervisors). В задачу последних входит слежение за рабочими процессами и другими процессами-наблюдателями — потомками. Деревья наблюдателей составляют OTP-приложение (англ. application)[114]. Документация по Erlang определяет OTP-приложение как компонент, реализующий некоторую функциональность, которая может быть независимо запущена на исполнение и остановлена как целое, а также повторно использована в других системах[115]. Разработчик приложения пишет код модулей функций обратного вызова (англ. call-back module), в которых и находится специфичная для данного приложения часть функциональности[114].

Хотя OTP строго говоря не является частью языка Erlang, он настолько вошёл в культуру и практику разработчиков на Erlang, что подчас между ними сложно провести границу[113].

Разработка графического интерфейса пользователя

[править | править код]

Разработка приложений с графическим интерфейсом пользователя (не считая веб-интерфейсов) может вестись при помощи библиотеки wxErlang — библиотеки wxWidgets, портированной для Erlang. WxErlang входит в стандартную поставку Erlang/OTP. WxWidgets написан на C++, поэтому перед разработчиками wxErlang стояла задача выразить средствами Erlang иерархию объектов. Несколько упрощая, в wxErlang классам соответствуют модули, а объектам — ссылки. Макросам на C++ соответствуют макросы Erlang. Некоторые типы данных, для которых в C++ были использованы классы, представляются в Erlang с помощью других типов данных, например, wxPoint задаётся в виде кортежа из двух элементов. События в wxErlang могут быть обработаны в Erlang либо с помощью функций обратного вызова (англ. call-back functions), либо более естественной в среде Erlang передачей сообщений[116].

Программирование на Erlang

[править | править код]

Интерактивная оболочка

[править | править код]
Интерактивная оболочка erl в отдельном окне

Интерактивная оболочка (англ. shell) для Erlang может быть вызвана в Unix-подобных системах по команде erl, в Windows — werl[117]. В оболочке можно вводить выражения и получать результат их выполнения, опробовать новый код, заниматься интерактивной отладкой, а также управлять системой, находящейся в промышленной эксплуатации[118].

В оболочке можно использовать дополнительные функции («команды»), доступные только в ней. Например, команда q(). осуществляет выход из оболочки с завершением всего, что делает Erlang-система[118].

В оболочке можно вызвать BREAK-меню с помощью Ctrl+C (в Unix-подобных ОС) или Ctrl+Break (в Windows). В этом меню есть различные команды, в том числе a — немедленный останов, c — продолжение работы в оболочке и другие информационные и вспомогательные команды для работы с Erlang-системой[118]. Комбинацией клавиш Ctrl+G вызывается ещё одно командное меню, с помощью которого можно, среди прочего, остановить «завесивший» оболочку процесс и вернуться в оболочку (i и затем c)[119].

Документирование и оформление кода

[править | править код]

Текст от знака процента (%) до конца строки считается комментарием в Erlang. Генерация документации из исходного кода в Erlang может производиться системой документирования EDoc. Для документирования кода модуля достаточно добавить определённым образом размеченный текст, а также файл overview.edoc для документации уровня проекта (в последнем необязательно использовать знаки комментария)[120]. Инструменты для работы с кодом на Erlang, например, erlang-режим в Emacs, подразумевают некоторые соглашения по употреблению символов комментария. Так, утроенный знак процента вызывает выравнивание по левому краю, удвоенный — выравнивание на уровне окружающего кода, а одиночный знак процента используется для обозначения комментария после кода, в конце строки[121]. Разработчики Erlang выработали определённые стилевые соглашения, касающиеся организации и оформления исходного кода. Например, хорошим стилем считается понижение вложенности синтаксических структур, написание коротких модулей (менее 400 строк кода) и функций (не длиннее 15-20 строк кода), использование осмысленных имён для переменных и функций и т. п.[122][123]

Типы и анализ кода

[править | править код]

Приложение Dialyzer, разработанное в рамках проекта HiPE и входящее в стандартную поставку, позволяет выявить ошибки (в том числе ошибки типизации) путём статического анализа кода. Программа TypEr, написанная Тобиасом Линдалом (Tobias Lindahl) и Костисом Сагонасом (Kostis Sagonas), является частью Dialyzer. Эта программа позволяет проверять определения типов функций, сверять указанный в директиве -spec тип функции с её определением, выполнить вывод типов[124]. Программа TypEr выводит все типы, соответствующие успешному применению функции, в общем случае — лишь приблизительно, в более грубую сторону. Использование функции любым другим способом обязательно приведёт к ошибке времени исполнения[124]. В следующем примере показан синтаксис определения типа (директива -type), объявление типа полей записи и директива -spec вместе с определением функции:

-type(user_status() :: disabled | enabled). % статус - один из двух атомов

-record(user, {login="anon" ::string(), % типы полей записи
               password ::string(),
               status :: user_status(),
               nickname ::string()}).

-spec(check_password(string(), #user{}) -> ok | {error, string()}). % объявление функции

check_password(Password, User) -> % определение функции
    ...

Dialyzer (от англ. DIscrepancy AnaLYZer for ERlang Programs — «анализатор противоречий для Erlang-программ») выявляет в коде отдельных модулей и целых приложений избыточные проверки, ошибки типов, недостижимый код. Все выявленные инструментом дефекты требуют устранения, так как инструмент не даёт ложных срабатываний. Для каждой функции всех проверяемых модулей Dialyzer устанавливает тип, используя основанный на ограничениях вывод типов и анализ потоков данных. После определения типов функций производится анализ противоречий в программе[125].

Тестирование, профилирование, рефакторинг

[править | править код]

Erlang предоставляет EUnit для модульного тестирования и фреймворк Common Test для системного тестирования. EUnit содержит средства для описания тестов, включая необходимый для этого набор макросов, а также производит вывод отчёта по окончании тестирования. Тестирование модулей происходит путём подключения заголовочного файла из EUnit, а функции с тестами могут быть как включены в сам тестируемый модуль, а так и вынесены в отдельный[126].

Тестирование параллельных программ можно выполнить с помощью Quviq Quick Check (версия Mini этого продукта доступна бесплатно)[127]. Кроме тестирования, можно провести проверку всех возможных вариантов исходных данных с помощью метода проверки моделей. Для этого можно воспользоваться созданной в Мадридском политехническом университете отдельно распространяемой утилитой McErlang[128].

Для профилирования кода и выявления степени покрытия кода тестами можно обратиться к модулям eprof, fprof, cover и утилите cprof[129].

Для Erlang разработаны несколько инструментов рефакторинга исходного кода, такие как RefactorErl, Wrangler, а также автоматическая, независимая от IDE утилита tidier. Утилита tidier позволяет автоматически находить и производить эквивалентные преобразование кода, например, заменяет

lists:filter(fun (X) -> is_something(X) end, L)

на

[X || X <- L, is_something(X)][130].

Эффективность

[править | править код]

Как и многие другие языки программирования, Erlang имеет свои секреты написания эффективного кода. Совершенствование языка делает некоторые из трюков устаревшими, поэтому документация является лучшим руководством в вопросах оптимизации, в совокупности с профилированием и стресс-тестированием.

Например, при работе со списками не рекомендуется добавлять элемент в конец длинного списка с помощью конкатенации или функции добавления элемента к списку. Вместо этого сто́ит рассмотреть возможность добавления элемента в начало списка, а конечный результат обработать функцией обращения порядка элементов списка[131].

Свои рекомендации есть и для увеличения эффективности параллельных программ. Например, действия, требующие много памяти, лучше всего выделять в отдельный процесс, так как при этом затраты на сборку мусора будут минимальны: память будет освобождена по завершении процесса[132].

Erlang и другие языки программирования

[править | править код]

Подробное сравнение возможностей Erlang с другими языками можно найти в статье сравнение языков программирования.

Интеграция и гибридные языки

[править | править код]

Erlang-система позволяет выполнять интеграцию с системами на других языках программирования. Имеются механизмы для сетевого взаимодействия с Си, Java, Лисп, Perl, Python, Ruby. Например, для более эффективного синхронного вызова небольших функций на Си можно использовать платформно-зависимые функции (англ. NIF, natively implemented function). Высокоуровневые библиотеки позволяют Erlang-системе представлять С или Java-узлы как обычные Erlang-узлы. Другие языки могут быть более тесно сопряжены со средой выполнения Erlang с помощью драйверов или сетевых сокетов посредством протоколов вроде HTTP, SNMP, IIOP[133]. Например, Ruby может взаимодействовать с Erlang посредством пакета erlectricity, а для Python разработана реализация Erlang-узла в виде пакета py-interface[134].

Виртуальная машина Erlang находит применение и в других языках программирования, например, Elixir[135][136] и проекте Erl2 Джо Армстронга[137][136]. Кроме того, Роберт Вирдинг поддерживает проект Lisp Flavored Erlang («Erlang, приправленный Лиспом»), в котором синтаксис Лиспа используется с компилятором Erlang[138]. Есть и другие BEAM-языки: Efene, Joxa, Reia[139], Luerl, Erlog[140].

Официальный сайт упоминает[141] проект Erjang[142], в котором используется виртуальная машина Java.

Сравнение Erlang и C++ по производительности

[править | править код]

Хотя опытные Erlang-программисты давно заметили, что их программы для тех же задач получаются более краткими по сравнению с другими широко используемыми в промышленности языками программирования, эмпирическое исследование показало, что для изученных телекоммуникационных приложений код на Erlang был на 70—85 % короче, чем на C++, а производительность системы при переписывании кода с C++ на Erlang возросла почти на 100 %[143][144]. Для одного из использованных в исследовании проектов разница была объяснена написанием дополнительного C++-кода в рамках защитного программирования, управления памятью и кода для высокоуровневой коммуникации, то есть возможностями, которые являются частью языка Erlang и библиотек OTP[144].

Сравнение взаимодействия процессов в Erlang и Go

[править | править код]

Влияние теории взаимодействующих последовательных процессов Чарльза Э. Хоара чувствуется как в Go, так и в Erlang. В Erlang процессы, в соответствии с моделью акторов, отправляют сообщения друг другу напрямую. В Go то же самое происходит посредством каналов (англ. channels)[145]. Другим отличием является то, что каналы в Go имеют типы. В Erlang же нет типизации времени компиляции за исключением охранных выражений, что позволяет посылать процессам сообщения любого типа, но «непонятое» сообщение либо будет проигнорировано, либо навсегда останется в очереди[145]. Go позволяет легко организовать группу «go-программ» (англ. goroutine — намёк на англ. co-routine — сопрограмма) для получения сообщений из некоторого канала (такой подход известен как пул потоков). В Erlang, при проектировании которого уделялось особое внимание детерминизму и времени задержки (англ. latency), реализация рабочего пула возможна, но требует дополнительных усилий. Множественные отправители тривиально реализуются в обоих языках[145]. Erlang-процесс может послать сообщение и ждать на него ответ (соответствующий некоторому образцу), игнорируя другие сообщения в очереди. В Go такое невозможно, но подобная функциональность может быть достигнута созданием (в том числе, динамическим) новых вводов, то есть разделением каналов по назначению[145]. Go требует явного указания того, какие go-программы будут взаимодействовать с другими передачей сообщений, тогда как в Erlang отсутствует разделяемое между процессами изменяемое состояние (англ. shared mutable state) и поэтому изолированный процесс очень редко представляет интерес[145].

Абстракции взаимодействующих процессов достаточно похожи в Erlang и Go, однако во избежание ошибок при переходе с одного языка на другой следует учитывать нюансы: шаблоны, которые хороши в одном языке, могут не подходить для другого[145].

Как и любой язык программирования, Erlang не свободен от недостатков[146]. К погрешностям синтаксиса можно отнести зависимость от символа окончания выражения от контекста (это может быть ., , или ;), что требует дополнительного внимания при перемене выражений местами, излишнюю многословность записей (тип записи приходится упоминать при каждом доступе к члену записи), необходимость полного перечисления альтернатив в if-выражении во избежание выбрасывания исключения, если ни одно из условий не выполнено. К недостаткам можно отнести строго ограниченный набор функций, которые можно использовать в if-выражениях (этот недостаток можно обойти использованием case-выражений). Функциональный стиль и неизменяемые переменные приводят в некоторых приложениях (например, тесты) к бо́льшему количеству правок, чем в других языках программирования, так как вставка некоторой промежуточной обработки может потребовать новых имён переменных, что может привести к изменениям в коде, следующем далее по тексту. Из недостатков системы типов можно указать отсутствие строкового типа, а также невозможность динамически добавлять в записи новые члены. Есть проблемы и с организацией исходного кода, которая возможна только через создание нового файла, а также отсутствие пространств имён, классов или других средств для организации кода. Уровень качества модулей, за исключением основных, и документации оставляет желать лучшего[146].

Один из создателей языка, Джо Армстронг, в своём выступлении на конференции по истории языков программирования в 2007 году перечислил список областей, в которых Erlang можно было бы улучшить[147]:

  • Использование сборки мусора для атомов.
  • Улучшение средств сопряжения со внешним кодом (англ. foreign code).
  • Усиление изоляции между процессами.
  • Более избирательная система безопасности среди узлов Erlang, основанная на различной степени доверия.
  • Отдельные обозначения для протоколов и систем.
  • Модули должны быть объектами первого класса.

Массовое распространение Erlang может сдерживать необычный для большинства программистов синтаксис, использование функциональной парадигмы, а также то, что наилучшая на 2010 год реализация языка использует виртуальную машину BEAM, а не более распространённую JVM[148].

Сфера применения

[править | править код]
Типичная архитектура системы, использующей Erlang/OTP. Приложения Erlang пользуются службами Mnesia, SASL, агентами SNMP-мониторинга и другими на базе фреймворка OTP, который в свою очередь использует ERTS. Программы других систем программирования поддерживаются в меньшей степени[149].

В силу своих особенностей Erlang и существующих библиотек модулей Erlang подходит для создания сетевых серверов, распределённых систем, программ с GUI и подобных им интерактивных программ, инструментов для тестирования, управления и слежения, в общем, приложений с нерегулярным параллелизмом, в которых распараллеливаемые задачи достаточно разнообразны. Erlang не особенно хорош для написания кода, содержащего интенсивные вычисления с плавающей запятой, требующего включения нативного кода конкретной платформы или сильной оптимизации, а также для создания приложений, требующих синхронного параллельного выполнения задач. Не подходит Erlang и для проектов, в которых код должен исполняться на JVM или CLR, или проектов, требующих множества библиотек из других систем программирования[150].

Можно сказать, что Erlang стал применяться для разработки облачных систем ещё до того, как сформировалось само понятие облачных вычислений[151]. Язык Erlang используется в масштабных телекоммуникационных и Интернет-приложениях многими компаниями, включая Amazon EC2 с реализацией SimpleDB, сервис социальных закладок Delicious, Facebook (бэкенд для чата), T-Mobile (сервис SMS и системы аутентификации)[152]. Серверное программное обеспечение WhatsApp написано на Erlang. В январе 2012 года серверы WhatsApp под FreeBSD с 96 ГБ оперативной памяти смогли обрабатывать от 1 до 2,8 миллиона соединений[153][154].

Erlang часто ставят в заслугу легендарную надёжность ATM-коммутатора AXD301 (полтора миллиона строк кода на Erlang, полмиллиона — на C/C++) в сети British Telecom. По данным Ericsson, с момента установки в январе 2002 года за несколько лет случилась только одна незначительная неполадка, на основании чего надёжность системы по расчётам составила 99,9999999 %[155]. Хотя более реальные оценки, учитывающие многие другие факторы, говорят всё-таки о «пяти девятках», успех маршрутизатора связывают с легкодоступными средствами разработки надёжных параллельных вычислений, встроенными в Erlang[155].

Используется Erlang и в приложениях с открытым исходным кодом, среди которых CouchDB — документо-ориентированная база данных с REST-интерфейсом, Disco — фреймворк для распределённых вычислений на основе парадигмы MapReduce[151][156], Ejabberd — свободный (GNU GPL), распределённый и устойчивый к отказам Jabber-сервер, написанный в основном на Erlang, RabbitMQ — платформа, ориентированная на обработку сообщений (реализует AMQP, MQTT[157]), Wings 3D — программа 3D-моделирования и другие.[152]

Для Erlang были написаны несколько веб-серверов: Yaws (англ. Yet Another Web Server), Cowboy, а также MochiWeb — библиотека для создания HTTP-серверов[158]. Кроме того, были созданы несколько веб-фреймворков и систем управления содержимым, таких как N2O[159], Nitrogen, Chicago Boss, Zotonic, а также более не разрабатываемые активно BeepBeep, Erlang Web, ErlyWeb[160].

Среди другого известного программного обеспечения, выполненного на Erlang, можно выделить распределённую NoSQL базу данных Riak, спроектированную по принципам Amazon DynamoDB[161], Flussonic (ранее известный как Erlyvideo) — видеостриминговый сервер, поддерживающий несколько протоколов[162]. Для стресс-тестирования распределённых систем можно применять (также распределённый) написанный на Erlang инструмент Tsung, который позволяет эмулировать тысячи (при достаточном количестве тестовых серверов — миллионы) одновременных пользователей[163].

Erlang практически идеально подходят для задач искусственного интеллекта (особенно вычислительного интеллекта, нейроэволюции), основанных на нейронных сетях. Подобное применение возможно благодаря имеющимся у Erlang пяти ключевым свойствам «языка программирования нейронных сетей»: изолированные процессы-нейроны (англ. encapsulation), параллелизм (англ. concurrency, одновременность), механизм обнаружения сбоев, независимость от местоположения (англ. location transparency) и горячая замена кода. Примером такого применения является реализация одного из подходов к нейроэволюции — DXNN[164].

Сообщество

[править | править код]

Вокруг технологий Erlang образовалось сообщество разработчиков, не отказывающее в поддержке новичкам. Исходный код Erlang доступен через сервис совместной разработки GitHub. Разработчики и пользователи Erlang могут общаться через список рассылки Erlang-questions (вопросы по Erlang) или на IRC-канале #erlang на Freenode. Erlang Factory (www.erlang-factory.com) устраивает по всему миру мероприятия и конференции, среди которых конференция пользователей Erlang (Erlang User Conference). Специальная группа SIGPLAN ACM регулярно проводит Erlang-мастерскую (Erlang Workshop), а конференция OSCON включает секцию по Erlang[165].

Примечания

[править | править код]
  1. Сайт проекта: The High-Performance Erlang Project. Uppsala University. Дата обращения: 6 декабря 2013. Архивировано из оригинала 16 июня 2011 года.
  2. Вариант с of употребляется редко.
  3. Флаг trap_exit можно установить с помощью функции process_flag/2.
  4. Правильно сформированная структура данных любого типа называется термом.
Источники
  1. Release 27.2 — 2024.
  2. Virding R. A History of the Erlang VM
  3. Erlang/OTP 18.0 has been released
  4. https://www.erlang.org/downloads
  5. Definition of «erlang» — Collins English Dictionary. Дата обращения: 7 января 2015. Архивировано 8 апреля 2015 года.
  6. Чезарини, Томпсон, 2012, с. 42.
  7. Dan McCreary, Ann Kelly, 2013, 10.3 Examples of functional programming languages.
  8. 1 2 3 4 5 Чезарини, Томпсон, 2012, с. 25—26.
  9. 1 2 Знакомьтесь, Erlang, 2009.
  10. 1 2 Armstrong, A History of Erlang, 2007, 6-14.
  11. Armstrong, A History of Erlang, 2007, 6-16.
  12. 1 2 Martin Logan, et al, 2011, p. xxxi.
  13. Bjarne Däcker, Master thesis, 2000, Backlash.
  14. 1 2 3 Чезарини, Томпсон, 2012, с. 26.
  15. 1 2 Armstrong, A History of Erlang, 2007, 6-17.
  16. 1 2 3 Martin Logan, et al, 2011, p. xxxii.
  17. Чезарини, Томпсон, 2012, с. 24—25.
  18. Armstrong, 2007.
  19. Lars-Åke Fredlund. Erlang – a platform for developing distributed software systems. — Component Based Software: 2011—2012, Universidad Politécnica de Madrid. Дата обращения: 6 декабря 2013. Архивировано 19 октября 2012 года.
  20. Чезарини, Томпсон, 2012, с. 381.
  21. EEP 0: Index of Erlang Enhancement Proposals (EEPs) (31 мая 2007). Дата обращения: 1 декабря 2013. Архивировано 1 октября 2013 года.
  22. Чезарини, Томпсон, 2012, с. 15.
  23. Cesarini, Thompson, 2009, p. 14.
  24. Simon St. Laurent, 2013, с. vii.
  25. Чезарини, Томпсон, 2012, с. 167.
  26. Tate, 2010, p. 183.
  27. Чезарини, Томпсон, 2012, с. 27.
  28. Чезарини, Томпсон, 2012, с. 117.
  29. Simon St. Laurent, 2013, с. 88.
  30. Чезарини, Томпсон, 2012, с. 117—118.
  31. 1 2 3 Чезарини, Томпсон, 2012, с. 30—31.
  32. Чезарини, Томпсон, 2012, с. 23—24.
  33. Чезарини, Томпсон, 2012, с. 29.
  34. 1 2 Joe Armstrong, Bjarne Däcker, Thomas Lindgren, Håkan Millroth, Erlang product team at Ericsson. Open-source Erlang — White Paper (англ.). Ericsson AB (2013). Архивировано 25 октября 2011 года.
  35. 1 2 Hebert, 2013, Types (or lack thereof).
  36. Чезарини, Томпсон, 2012, с. 39.
  37. Hebert, 2013, Type Specifications and Erlang.
  38. Чезарини, Томпсон, 2012, с. 38—39.
  39. math, STDLIB Reference Manual Version 1.19.3 (англ.). Ericsson AB (2013). Дата обращения: 1 декабря 2013. Архивировано 2 декабря 2013 года.
  40. Martin Logan, et al, 2011, p. 31—32.
  41. 1 2 Чезарини, Томпсон, 2012, с. 41—42.
  42. Simon St. Laurent, 2013, с. 172.
  43. Чезарини, Томпсон, 2012, с. 230—235.
  44. Чезарини, Томпсон, 2012, с. 233—234.
  45. 1 2 Чезарини, Томпсон, 2012, с. 44—45.
  46. Чезарини, Томпсон, 2012, с. 48—51.
  47. Чезарини, Томпсон, 2012, с. 47—48.
  48. Hebert, 2013, Starting Out (for real).
  49. Чезарини, Томпсон, 2012, с. 48—50.
  50. Чезарини, Томпсон, 2012, с. 223.
  51. Simon St. Laurent, 2013, с. 84—85.
  52. Simon St. Laurent, 2013, с. 62.
  53. Чезарини, Томпсон, 2012, с. 46.
  54. Чезарини, Томпсон, 2012, с. 43.
  55. 1 2 Simon St. Laurent, 2013, с. 17.
  56. 1 2 3 Martin Logan, et al, 2011, p. 69—71.
  57. Data Types, Erlang Reference Manual User's Guide Version 5.10.3 (англ.). Ericsson AB (2013). Дата обращения: 1 декабря 2013. Архивировано 2 декабря 2013 года.
  58. Чезарини, Томпсон, 2012, с. 238.
  59. 1 2 3 Martin Logan, et al, 2011, p. 36.
  60. Ports and Port Drivers, Reference Manual User's Guide Version 5.10.3 (англ.). Ericsson AB (2013). Дата обращения: 1 декабря 2013. Архивировано 3 декабря 2013 года.
  61. Чезарини, Томпсон, 2012, с. 40—41.
  62. Чезарини, Томпсон, 2012, с. 235—236.
  63. Чезарини, Томпсон, 2012, с. 43—44.
  64. 1 2 Чезарини, Томпсон, 2012, с. 51—52.
  65. 1 2 Чезарини, Томпсон, 2012, с. 53—55.
  66. Zachary Kessin, 2012, p. 2—3.
  67. Чезарини, Томпсон, 2012, с. 74.
  68. Martin Logan, et al, 2011, p. 56.
  69. Чезарини, Томпсон, 2012, с. 57—62.
  70. Чезарини, Томпсон, 2012, с. 62—65.
  71. Душкин Р. Функциональное программирование на языке Haskell. — ДМК-Пресс, 2007. — С. 120. — 608 с. — ISBN 5-94074-335-8.
  72. Simon St. Laurent, 2013, с. 30—31.
  73. Simon St. Laurent, 2013, с. 32.
  74. Simon St. Laurent, 2013, с. 51.
  75. Чезарини, Томпсон, 2012, с. 220.
  76. Чезарини, Томпсон, 2012, с. 71—73.
  77. Чезарини, Томпсон, 2012, с. 75—76.
  78. Simon St. Laurent, 2013, с. 42.
  79. Simon St. Laurent, 2013, с. 44—45.
  80. Чезарини, Томпсон, 2012, с. 193.
  81. Чезарини, Томпсон, 2012, с. 194—195.
  82. The Preprocessor, Predefined Macros, Erlang Reference Manual User's Guide Version 5.10.3 (англ.). Ericsson AB (2013). Дата обращения: 1 декабря 2013. Архивировано 2 декабря 2013 года.
  83. Чезарини, Томпсон, 2012, с. 196—197.
  84. Чезарини, Томпсон, 2012, с. 98.
  85. Simon St. Laurent, 2013, с. 108.
  86. 1 2 3 Чезарини, Томпсон, 2012, с. 98—102.
  87. Simon St. Laurent, 2013, с. 110.
  88. Чезарини, Томпсон, 2012, с. 102.
  89. 1 2 Чезарини, Томпсон, 2012, с. 65—66.
  90. 1 2 Hebert, 2013, Modules.
  91. Simon St. Laurent, 2013, с. 18.
  92. Martin Logan, et al, 2011, p. 75.
  93. 1 2 Чезарини, Томпсон, 2012, с. 120—124.
  94. Чезарини, Томпсон, 2012, с. 118—120.
  95. Чезарини, Томпсон, 2012, с. 167—168.
  96. Cesarini, Thompson, 2009, p. 139.
  97. Чезарини, Томпсон, 2012, с. 168—169.
  98. Чезарини, Томпсон, 2012, с. 170—171, 175.
  99. Чезарини, Томпсон, 2012, с. 176—177.
  100. Чезарини, Томпсон, 2012, с. 172—174.
  101. Чезарини, Томпсон, 2012, с. 174.
  102. Martin Logan, et al, 2011, p. 19.
  103. Чезарини, Томпсон, 2012, с. 83—84.
  104. The Erlang I/O-protocol, STDLIB User's Guide Version 1.19.4 (англ.). Ericsson AB (2013). Дата обращения: 21 декабря 2013. Архивировано 24 декабря 2013 года.
  105. Cesarini, Thompson, 2009, p. 79.
  106. STDLIB Reference Manual Version 1.19.3 (англ.). Ericsson AB (2013). Дата обращения: 1 декабря 2013. Архивировано 3 декабря 2013 года.
  107. STDLIB, STDLIB Reference Manual Version 1.19.3 (англ.). Ericsson AB (2013). Дата обращения: 1 декабря 2013. Архивировано 7 ноября 2013 года.
  108. Чезарини, Томпсон, 2012, с. 107—108.
  109. Simon St. Laurent, 2013, с. 131.
  110. Чезарини, Томпсон, 2012, с. 241—247.
  111. Чезарини, Томпсон, 2012, с. 257.
  112. Чезарини, Томпсон, 2012, с. 291.
  113. 1 2 Simon St. Laurent, 2013, с. 151.
  114. 1 2 Чезарини, Томпсон, 2012, с. 291—294.
  115. application, Kernel Reference Manual Version 2.16.3 (англ.). Ericsson AB (2013). Архивировано 1 ноября 2013 года.
  116. Чезарини, Томпсон, 2012, с. 337—339,348.
  117. Simon St. Laurent, 2013, с. 2—3.
  118. 1 2 3 Martin Logan, et al, 2011, p. 23—27.
  119. Hebert, 2013, Starting Out.
  120. Simon St. Laurent, 2013, с. 20—21.
  121. Simon St. Laurent, 2013, с. 21.
  122. Klas Eriksson, M. Williams, J. Armstrong. Programming Rules and Conventions. Ericsson AB. Дата обращения: 2 декабря 2013. Архивировано 30 ноября 2013 года.
  123. Чезарини, Томпсон, 2012, с. 460—465.
  124. 1 2 Чезарини, Томпсон, 2012, с. 424—430.
  125. Aronis, et al, 2012.
  126. Чезарини, Томпсон, 2012, с. 442.
  127. Чезарини, Томпсон, 2012, с. 449—450.
  128. Чезарини, Томпсон, 2012, с. 449—450,478.
  129. Simon St. Laurent, 2013, с. 166—167.
  130. Avgerinos, Sagonas, 2009.
  131. Чезарини, Томпсон, 2012, с. 470.
  132. Чезарини, Томпсон, 2012, с. 471.
  133. Чезарини, Томпсон, 2012, с. 31.
  134. Zachary Kessin, 2012, p. 125—128.
  135. elixir (англ.). Plataformatec (2013). Дата обращения: 1 декабря 2013. Архивировано 18 апреля 2012 года.
  136. 1 2 Simon St. Laurent, 2013, с. 168.
  137. Joe Armstrong. erl2, a new dialect of erlang (англ.) (2013). Дата обращения: 1 декабря 2013. Архивировано 5 сентября 2013 года.
  138. Lisp Flavored Erlang (англ.). Дата обращения: 8 декабря 2013. Архивировано 13 декабря 2013 года.
  139. Why I’m stopping work on Reia Архивная копия от 15 сентября 2015 на Wayback Machine, 2011
  140. Federico Carrone, et al Spawned Shelter! Архивная копия от 5 ноября 2015 на Wayback Machine
  141. Academic and Historical Questions (англ.). Ericsson AB (2013). Дата обращения: 1 декабря 2013. Архивировано 6 октября 2013 года.
  142. Welcome to Erjang! (англ.). Trifork A/S (2013). Дата обращения: 1 декабря 2013. Архивировано 10 марта 2017 года.
  143. Nyström, Trinder, King, 2008.
  144. 1 2 Чезарини, Томпсон, 2012, с. 35—36.
  145. 1 2 3 4 5 6 David Chisnall. A Tale of Two Concurrency Models: Comparing the Go and Erlang Programming Languages (англ.). Pearson Education, Informit (14 ноября 2011). Дата обращения: 1 декабря 2013. Архивировано 3 декабря 2013 года.
  146. 1 2 Damien Katz (создатель CouchDB). What Sucks About Erlang (англ.) (9 марта 2008). Дата обращения: 24 ноября 2013. Архивировано 5 декабря 2013 года.
  147. Armstrong, A History of Erlang, 2007, 6-19,6-20.
  148. Tate, 2010, p. 221.
  149. Dan McCreary, Ann Kelly, 2013.
  150. Larson, Erlang for Concurrent Programming, 2008.
  151. 1 2 Ной Гифт. Работа с большими объемами данных в облаке с помощью MapReduce. IBM (1 марта 2012). Дата обращения: 7 декабря 2013. Архивировано 11 декабря 2013 года.
  152. 1 2 Чезарини, Томпсон, 2012, с. 23—25.
  153. Scaling to Millions of Simultaneous Connections Архивная копия от 9 июля 2012 на Wayback Machine, Rick Reed (WhatsApp) // Erlang Factory SF, March 30, 2012
  154. 1 million is so 2011 Архивная копия от 19 февраля 2014 на Wayback Machine // WhatsApp Blog, January 6, 2012
  155. 1 2 Чезарини, Томпсон, 2012, с. 33.
  156. Disco (страница проекта). Дата обращения: 7 декабря 2013. Архивировано 16 сентября 2010 года.
  157. Pivotal Software, Inc. RabbitMQ MQTT Adapter. Дата обращения: 10 декабря 2015. Архивировано 1 декабря 2015 года.
  158. Martin Brown. Introduction to programming in Erlang, Part 2: Use advanced features and functionality (англ.). IBM (2013). Дата обращения: 1 декабря 2013. Архивировано 3 декабря 2013 года.
  159. Выпущен новый веб-фреймворк N2O на языке Erlang. linux.org.ru. Дата обращения: 13 декабря 2014. Архивировано 14 декабря 2014 года.
  160. Zachary Kessin, 2012, p. 121—123.
  161. Simon St. Laurent, 2013, с. 167.
  162. Flussonic — мультипротокольный видеостриминговый сервер. Flussonic, LLC. Дата обращения: 7 мая 2012. Архивировано 16 июня 2012 года.
  163. Bradley Holt. Chapter 6. Distributed Load Testing // Scaling CouchDB. — O'Reilly Media, Inc., 2011. — P. 39. — 72 p. — ISBN 978-1-4493-0343-3.
  164. Sher, 2013, Chapter 5 The Unintentional Neural Network Programming Language, pp. 144—150.
  165. Simon St. Laurent, 2013, с. 168—169.

Литература

[править | править код]
на русском языке
  • Чезарини Ф., Томпсон С. Программирование в Erlang = Erlang Programming. — М.: ДМК Пресс, 2012. — 488 с. — ISBN 978-5-94074-617-1.
  • Хеберт Ф. Изучай Erlang во имя добра! = Learn You Some Erlang for Great Good! — М.: ДМК Пресс, 2015. — 686 с. — ISBN 978-5-97060-086-3.
  • Чезарини Ф., Виноски С. Проектирования масштабируемых систем в Erlang/OTP = Designing for Scalability with Erlang/OTP. — ДМК Пресс, 2017. — 486 с. — ISBN 978-5-97060-212-6.
на английском языке