Написал свой первый простенький скрипт на Erlang
25 июля 2012
Что не говори, а изучение новых языков программирования редко оказывается пустой тратой времени. Даже если изучаемый язык не придется использовать на практике, в процессе изучения вы скорее всего в той или иной мере сломаете себе мозг (в хорошем смысле), то есть, откроете для себя новые подходы к решению неких проблем. В дальнейшем эти подходы могут быть использованы вами независимо от языка программирования.
Об 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(dates).
-define(JULY, 7).
-define(FRIDAY, 4).
sys_admin_day_in_year(Y) ->
Pred = fun(D) -> dates: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 после года работы с ним
Метки: Erlang, Функциональное программирование, Языки программирования.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.