Чтобы писать веб-приложения на эрланге, надо его хотя бы немного знать, поэтому попробую в пару постов уложить основные понятия.
Тут лучше конечно почитать какой-нибудь более серьезный туториал, начиная с собственно "Getting Started with Erlang" (русский перевод на рсдн), или "Thinking In Erlang". Однако ж, поскольку 30-50 страниц осилить не у каждого поднимется мозг, я здесь изобразил небольшую шпаргалку (не претендующую на полноценное введение).
В принципе Эрланг весьма прост, по крайней мере для тех, кто хоть краем глаза видел какой-нибудь другой функциональный язык.
Для начала самые примитивные вещи:
-
Прежде всего, Эрланг — это язык с динамической типизацией, никакой статической проверки типов тут нет.
- Литералы-числа в Erlang: 1, 4, 15, 25, 16#1F (в шестнадцатеричной системе), 2#01110110 (в двоичной).
> 1.
1
> 1+2.
3
> 1+1.5.
2.50000 - Литералы-символы: на самом деле это не отдельный тип, а просто целое число — код символа : $a, $b, $\n $_
> $a.
97
> $\n.
10 - Списки задаются в квадратных скобках:
> [].
[]
> X = [1,2].
[1,2].
> [3 | X].
[3, 1, 2] - Строки — "aba a", "ga a ga".
> [$a, $b, $c]. "abc"
Строки — это на самом деле просто списки символов. Поэтому памяти они занимают немало — в общей сложности 8 байт на один символ строки (на 32-битной машине).
- Битовые строки (binaries) — эффективное представление бинарных данных
> <<1, 3, "ba">>. <<1,3,98,97>>
Их можно сопоставлять с шаблонами, и быстро передавать туда-сюда. Очень полезная фича Эрланга (правда мы ее использовать сильно не будем). - Атомы
abds more hello ok undefined
Начинаются с маленькой буквы, и представляют собой что-то среднее между enum'ами и константными строками, пишутся без кавычек и удобны для разных меток и идентификаторов. Атомы очень похожи на строки, но их нельзя склеивать, вычислять длину и пр., длина их ограничена 256 байтами. Они существенно эффективнее строк в обращении. - Еще любые значения еще можно объединять в пары, тройки, четверки, пятерки и так далее, с помощью фигурных скобок:
{14, 15} {0, "ba", 3} {$a, [1,2], {3,4}}
Имена переменных всегда начинаются с большой буквы (несмотря на то что они везде называются "переменными", менять их нельзя).
Имена функций и модулей обязательно начинаются с маленькой буквы. Сигнатура функции состоит из ее имени и количества параметров — то есть format/2 и format/3 это разные функции.
Паттерн матчинг (сопоставление с шаблоном) в Erlang выглядит так:
case A of Pattern1 -> ...; Pattern2 -> ...; Pattern3 -> ...; end
В паттернах можно использовать значок _ который матчит все что угодно (wildcard). В жизни используется как-то так:
case Foo of {"HELLO", Name} -> send_response("Hello, " ++ Name); "BYE" -> send_response("Bye"); _ -> send_response("Unknown command") end
Еще паттерны можно использовать прямо в списке параметров функции:
foo({_, B}) -> ...; foo(X) -> ...
что эквивалентно
foo(Y) -> case Y of {_, B} -> ... X -> ... end.
Плюс, значения можно матчить с помощью знака "равно":
X = {1, 3}, {A, B} = X.
теперь A = 1, а B = 3
Причем, если переменная слева уже определена, в паттерне используется ее значение:
> B = 4.
Получаем run-time ошибку badmatch, потому что B у нас уже равно трем.
С операторами все почти как обычно:
- арифметические, +-/*%
- сравнения =/ , ==, =>, =<
- склеивание списков ++
- декомпозиция списков (оператор cons) |
- битовые band, bor, bxor, bnot
Вот, собственно, практически все. Раздражают в Эрланге поначалу только немного странные правила расстановки точек, запятых и точек с запятой. В двух словах — точка ставится в конце определения функции, запятая — между выражениями в определении функции, а точка с запятой разделяет выражения в case .. of и if.
В качестве примера — функция, получающая md5 хэш строки. В стандартной библиотеке уже есть функция md5(), которая получает хэш в виде битовой строки.
> H = erlang:md5("boooo").
<<174,62,131,226,250,179,167,216,104,61,142,239,171,209,231,77>>
Нам же понадобится хэш в виде обычной строки, в шестнадцатиричном представлении, поскольку он используется в процедуре аутентификации на last.fm
Для начала можно преобразовать битовую строку в список байт с помощью стандартной функции:
> binary_to_list(H).
[174,62,131,226,250,179,167,216,104,61,142,239,171,209,231,77]
Теперь функция, которая преобразует 4 бита в один hex символ:
hex(V) -> if V < 10 -> $0 + V; true -> $a + (V - 10) end.
Да, if в erlang — лишь упрощенный вариант case .. of, где вместо паттернов — булевые выражения. Так что кейс "true ->" тут играет роль else
Теперь один байт можно преобразовать в hex так:
> E = 31.
> [hex(E bsr 4), hex(E band 16#F)].
"1f"
Ну и с помощью функции lists:foldl применить это ко всей исходной строке:
binary_to_hex(Bin) -> lists:foldl(fun (E, Acc) -> [hex(E bsr 4) | [hex(E band 16#F) | Acc]] end, [], lists:reverse(binary_to_list(Bin))). % returns hex representation of md5 in reverse byte order md5_hex(Bin) -> binary_to_hex(erlang:md5(Bin)).
Тут
- fun (E, Acc) -> ... end
это определение лямбда-функции - lists:foldl() это известный функциональным программистам foldl.
- lists:reverse() разворачивает список задом наперед
- Конструкция вида [A | B] приклеивает в начало списка B элемент A (см. cons).
Итого получаем
Про ключевую фичу Erlang — поддержку распределенных приложений поговорим в следующей серии.>md5_hex("booo").
"1c052f260d1b34423c32e7c7b29026b9"