Что не говори, а изучение новых языков программирования редко оказывается пустой тратой времени. Даже если изучаемый язык не придется использовать на практике, в процессе изучения вы скорее всего в той или иной мере сломаете себе мозг (в хорошем смысле), то есть, откроете для себя новые подходы к решению неких проблем. В дальнейшем эти подходы могут быть использованы вами независимо от языка программирования.

Об Erlang много пишут в этих ваших интернетах, дескать он нашел широкое применение в разработке высоконагруженных отказоустойчивых приложений. Кроме того, недавно вышел русский перевод книги «Erlang Programming». Данные обстоятельства и послужили мне стимулами для изучения Erlang.

Краткая информация о языке:

  • Erlang — функциональный язык программирования (правда, не чистый, как Haskell ) со строгой динамической типизацией ;
  • Программы на Erlang транслируются в байт-код, который затем выполняется виртуальной машиной;
  • Аргументы передаются функциям только по значению, глобальные переменные и указатели отсутствуют, присвоение значений переменным допускается только при их объявлении, управление памятью происходит автоматически ;
  • Прочие фишки функционального программирования — сопоставление с образцом, «лямбды», замыкания, REPL-разработка и тп, правда нет поддержки каррирования и ленивых вычислений ;
  • Есть поддержка исключений;
  • Легковесные процессы, отсутствие разделяемой памяти (чуть подробнее об этом будет рассказано ниже);
  • Развитый инструментарий — EUnit и Common Test для написания тестов , EDoc для документирования кода, Dialyzer для проверки типов и TypeEr для автоматического вывода типов (в языке с динамической типизацией!), Rebar для сборки проектов и установки зависимостей, dbg для отладки, а также xref, erl_tidy и другие;
  • Большое количество годных библиотек и фреймворков, а также исчерпывающая документация к ним;
  • Широкая область применения — на Erlang написаны XMPP-сервер ejabberd, СУБД Mnesia, CouchDB , Couchbase , Scalaris и Riak , система обмена сообщениями RabbitMQ , программа 3D-моделирования Wings 3D , видеостриминговый сервер Erlyvideo, веб-серверы Cowboy и Yaws, веб-фреймворк Nitrogen, серверная часть игры Call of Duty, Map-Reduce фреймворк Disco, CMS Zotonic, распределенная система нагрузочного тестирования Tsung , сервер API системы управления конфигурацией Chef и другие ;
  • Используется в Yahoo, Amazon, Facebook, Motorola, Ericsson, Яндексе, WhatsApp, Nokia, GitHub, Blizzard, Hypercomments и не только;

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

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

Благодаря описанной модели, Erlang-процессы могут быть с легкостью распределены как по ядрам одного процессора, так и по нескольким компьютерам, объединенным в сеть . Кроме того, в Erlang предусмотрены средства, позволяющие обновлять код приложения без его остановки . Следует также отметить возможность создания процессов-наблюдателей, которые, к примеру, могут перезапускать всю группу зависящих друг от друга процессов в случае возникновения исключения в одном из них.

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

module ( date s ) .
import ( lists ) .
% -compile(export_all).
export ( [ is_leap_year / 1 , days_in_year / 1 , days_in_month / 2 ,
days_from_epoch / 3 , day_of_week / 3 ] ) .

define ( DEBUG , false ) .

define ( JANUARY , 1 ) .
define ( FEBRUARY , 2 ) .
define ( APRIL , 4 ) .
define ( JUNE , 6 ) .
define ( SEPTEMBER , 9 ) .
define ( NOVEMBER , 11 ) .
define ( DECEMBER , 12 ) .

ifdef ( DEBUG ) .
define ( CHECK_MONTH ( Month ) ,
case ( Month >= ? JANUARY ) and ( Month =< ? DECEMBER ) of
false -> erlang : error ( badarg ) ;
_ -> ok
end
) .

else .
define ( CHECK_MONTH ( _ ) , ok ) .
endif .

is_leap_year ( Y ) ->
if
Y rem 400 == 0 -> true ;
Y rem 100 == 0 -> false ;
Y rem 4 == 0 -> true ;
true -> false
end .

days_in_year ( Y ) ->
case is_leap_year ( Y ) of
true -> 366 ;
false -> 365
end .

days_in_month ( ? FEBRUARY , IsLeapYear ) ->
if
IsLeapYear -> 29 ;
true -> 28
end ;
days_in_month ( Month , _ ) ->
? CHECK_MONTH ( Month ) ,
case lists : member (
Month ,
[ ? APRIL , ? JUNE , ? SEPTEMBER , ? NOVEMBER ] ) of
true -> 30 ;
_ -> 31
end .

months_before ( ? JANUARY ) -> [ ] ;
months_before ( Month ) ->
? CHECK_MONTH ( Month ) ,
[ Month 1 | months_before ( Month 1 ) ] .

% число дней с 1-го января 1-го года (не включая)
days_from_epoch ( Year , Month , Day ) ->
? CHECK_MONTH ( Month ) ,
IsLeap = is_leap_year ( Year ) ,
YDays = lists : map ( fun days_in_year / 1 , lists : seq ( 1 , Year 1 ) ) ,
MDays = lists : map (
fun ( M ) -> days_in_month ( M , IsLeap ) end ,
months_before ( Month ) ) ,
lists : sum ( YDays ) + lists : sum ( MDays ) + Day 1 .

day_of_week ( Year , Month , Day ) ->
days_from_epoch ( Year , Month , Day ) rem 7 .

А вот и скрипт main.erl, определяющий, на какое число июля приходится день системного администратора в 2012-ом году:

# !/ usr / bin / env escript

import ( lists ) .
import ( date s ) .

define ( JULY , 7 ) .
define ( FRIDAY , 4 ) .
sys_admin_day_in_year ( Y ) ->
Pred = fun ( D ) -> date s: day_of_week ( Y , ? JULY , D ) == ? FRIDAY end ,
lists : last ( lists : filter ( Pred , lists : seq ( 1 , 31 ) ) ) .

main ( _Args ) ->
io : format ( «~w n » , [ sys_admin_day_in_year ( 2012 ) ] ) .

Установка Erlang и запуск скрипта:

sudo apt-get install erlang
chmod u+x . / main.erl
. / main.erl

Тут, конечно, никаким хайлоадом или распределенностью даже не пахнет, но, думаю, синтаксис я уже более-менее освоил. Запустив скрипт, мы узнаем, что день сисадмина в этом году приходится на 27-е июля. Не забудьте поздравить знакомых админов!

Узнать больше об Erlang можно из книги Learn You Some Erlang for Great Good . Это аналог книги «Изучай Haskell во имя добра», только про Erlang.

Дополнение: Впечатления от Erlang после года работы с ним

EnglishRussianUkrainian