Что не говори, а изучение новых языков программирования редко оказывается пустой тратой времени. Даже если изучаемый язык не придется использовать на практике, в процессе изучения вы скорее всего в той или иной мере сломаете себе мозг (в хорошем смысле), то есть, откроете для себя новые подходы к решению неких проблем. В дальнейшем эти подходы могут быть использованы вами независимо от языка программирования.
Об 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 в качестве такого прототипа я выбрал программу, решающую задачу о дне системного администратора . В результате у меня получилась такая библиотека для работы с датами:
— 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-ом году:
— 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 и запуск скрипта:
chmod u+x . / main.erl
. / main.erl
Тут, конечно, никаким хайлоадом или распределенностью даже не пахнет, но, думаю, синтаксис я уже более-менее освоил. Запустив скрипт, мы узнаем, что день сисадмина в этом году приходится на 27-е июля. Не забудьте поздравить знакомых админов!
Узнать больше об Erlang можно из книги Learn You Some Erlang for Great Good . Это аналог книги «Изучай Haskell во имя добра», только про Erlang.
Дополнение: Впечатления от Erlang после года работы с ним