Чтобы писать веб-приложения на эрланге, надо его хотя бы немного знать, поэтому попробую в пару постов уложить основные понятия.
Тут лучше конечно почитать какой-нибудь более серьезный туториал, начиная с собственно "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"
25 comments:
Отлично! Наверное было бы неплохо сразу рассказать и о том, как написаное сохранить в файл/вызвать оттуда, чтобы экспериментировать было попроще (-module(md5hex). -export(md5_hex/1) или чего-нибудь подобное).
Честно сказать, выглядит ужасающе. :) Синтаксис, конечно, ОЧЕНЬ непривычный.
Хотя некоторые элементы знакомы:
списки - из питона
{} - это тоже из питона (только там круглые скобки "()"), кортежами называется
атомы - очень напоминают :string из ruby
"Паттерн матчинг" - выражения, конечно, заумные. :) Всегда switch был.
Ну это я так...
> foo({_, B}) ->
Поясни "_". В функцию мы передаем кортеж (один аргумент) из двух элементов. Мы на тип первого аргумента никаких ограничений не накладываем. Зачем тогда wildcard? Ведь оно по сути аналогично foo({A, B}). Или я где-то недопонял?
PS. Сорри, читать маны как-то неохота. :)
PPS. Кажись, ты на работе на C++ пишешь. Откуда такая тяга к функциональщине? Или почему ты всё-же работаешь C++-программистом?
о. люблю такие посты.
будем ждать про написание распределёнщины.
fxposter>
Да, кстати -- для питоновода тут особенных проблем быть не должно, а атомы это действительно то же самое что ruby symbols.
switch это не совсем то, switch это ведь то же самое что
if (X == A) then ..
elseif (X == B) then ...
elseif (X == C) then ...
А паттерн матчинг более мощная вещь:
if (match(X, A)) then ..
elseif (match(X, B)) then ...
elseif (match(X, C)) then ...
Да, foo({_, B}) будет иметь тот же эффект что и foo({A, B}), но если A нас не интересует, лучше вместо него подставить "_". Особенно это удобно в случаях типа foo({_, _, _, _, B, _, _})
P.S. Насчет C++ все просто: все-таки тяга к функциональщине -- сама по себе недостаточно мощная причина, чтобы менять работу, есть еще много других факторов :)
Wunar>
Сложно все впихнуть в один пост %) В принципе это все можно и прямо в интерпретаторе набирать.
Но я на всякий случай еще приаттачил сейчас исходник модуля (см. в конце), и там кое-какие пояснения есть по этому поводу.
На самом деле в Ruby тогда тоже не обычный switch/case, а такой вот "паттерн-матчинг", ведь можно использовать регекспы:
case (x)
when /^x.*/ ...
when /^a.b$/ ...
...
выглядит как на скорую руку написанный для игрушки скриптовый язык
>>Да, foo({_, B}) будет иметь тот же эффект что и foo({A, B}), но если A нас не интересует, лучше вместо него подставить "_". Особенно это удобно в случаях типа foo({_, _, _, _, B, _, _})
Скорее, лучше сказать, что в случае с foo({A, B}) и неиспользованием A будет ворнинг, а мы ведь ворнинги не любим :) На самом деле, _ - просто анонимная переменная. Дабы подавить сообщение о ворнинге можно также использовать имена переменных, начинающихся с _, например foo({_Name, _Message, Login, Password, _, _, _}). Это удобней - видно, что предполагается передавать, хотя различия есть: {_,_}={20,30} прокатит, а {_A,_A}={20,30} - нет.
P.S. С интересом буду следить. Пока изучу джангу, хотя может потом вернусь к Эрлангу - уж очень он приятен :)
На мой взгляд, еще вот сюда стоит заглянуть, очень так же крайне полезно.
http://gzip.rsdn.ru/article/erlang/GettingStartedWithErlang.xml
edoc_modnar> Но там это только для строк работает, насколько я понимаю?
Сергей Кищенко> Да, спасибо -- про _A я не знал :)
kaa.python> Спасибо, добавил ссылку
А-а-а-а-аааааааааа!!!!! Я сошел с ума. Большое спасибо. Моск взорвался :) Теперь понимаю, что есть языки, которые фортрану77 никогда не догнать по сложности прочтения кода. Хотя он наверно проектировался не для читателей, а для писателей.
Большой> Это у вас просто с непривычки. Эрланг действительно очень прост, конструкций и ключевых слов можно по пальцам пересчитать, никакого груза "обратной совместимости". Он в общем-то и создавался с прицелом на то чтобы среднего инженера ему можно было научить за пару недель.
Кстати синтаксис там во многом от Пролога, и первая версия Erlang на Прологе была написана.
1) А как запустить erl-файл?
2) Как ввести с клавиатуры два числа, и вывести их сумму?
Там на RSDN рассказывается как запустить из интерпретатора
c(модуль)
модуль:функция
, как это сделать из обычной командной строки?
C:\test\erl>dir /b c:\soft\dev\erl5.6\bin
dialyzer.exe
erl.exe
erl.ini
erlc.exe
escript.exe
start.boot
start_clean.boot
start_sasl.boot
typer.exe
werl.exe
И ещё такой вопрос, как выйти из интерпретатора? Когда я нажимаю на Ctrl+C он почему-то падает.
erl.exe - Ошибка приложения
Инструкция по адресу "0x00922f91" обратилась к памяти по адресу "0x00000114". Память не может быть "read".
Что бы люди загорелись, надо рассказать как правильно запустить %)
_winnie>
На самом деле эрланг это такая хрень которая изначально предназначена для написания серверов. Поэтому из командной строчки запускать не очень удобно.
Я обычно делаю так:
Сначала компилируем в beam
erlc -W module
Потом запускаем
erl -run Module Function [Args..]
Правда после того как функция отработает, интерпретатор останется висеть. Более правильный вариант -- сделать приложение (Application), но это надо маны почитать.
И ближе к тому что надо -- интерфейс для скриптинга через escript, у модуля должна быть функция main/1, запускать соотв-но как escript myapp.erl
Насчет Ctrl+C не могу ничего сказать сейчас, винды под рукой нету :)
Кста про матчинг. Там when есть.
% поиск в списке max значения
-module(tut6).
-export([list_max/1]).
list_max([Head | Rest]) ->
list_max(Rest, Head).
list_max([], Res) ->
Res;
list_max([Head | Rest], Result_so_far) when Head > Result_so_far ->
list_max(Rest, Head);
list_max([Head | Rest], Result_so_far) ->
list_max(Rest, Result_so_far).
39> c(tut6).
{ok, tut6}
40> tut6:list_max([1, 2, 3, 4, 5, 7, 4, 3, 2, 1]).
7
взято там-же http://gzip.rsdn.ru/article/erlang/GettingStartedWithErlang.xml
-1) А как запустить erl-файл?
сначала скомпилировать
1 в шеле c(module). и запустить module:fun().
2 в командной строке:
erlc fac1.erl компилируем, запускаем
erl -noshell -s module fun param
тк интерпритатор сам не завершается - можно добавить -s init stop
или прописать init:stop(). в конце программы в erl файле.
-Когда я нажимаю на Ctrl+C он -почему-то падает.
ctrl+break под win
под win, кста, удобно использовать файлик .erlang положив его в папку, куда поставлен ерланг. а в нём прописать примерно так:
c:cd("C:/progect/erlang/code" ).
io:format("Now in:~p~n" , [element(2,file:get_cwd())]).
забыл..
escript под win так и не получилось запустить, если ко-то осилит, поделитесь, пожалуйста, рецептом.
Гм, у меня escript под виндой без проблем запустился
edain> Я не то что бы большой борец за авторские права, но тыреные ебуки по теме интересующиеся и сами смогут легко найти на варезных порталах. Здесь им не место.
А есть язык типа эрланг, но заточенный для создания десктоп приложений?
hex(V) when V < 10 ->
$0 + V;
hex(V) ->
$a + (V - 10).
не могли бы подсказать как erlang и русский подружить, а то "Привет мир"
2> tut:helloword(1).
\320\237\321\200\320\270\320\262\320\265\321\202 \320\274\320\270\321\200!ok
(erland R12 + fedora)
Гм на самом деле точно не знаю, знаю только что такая проблема есть. Для работы с юникодными строками вообще библиотеки, конечно, существуют, но вот чтоб именно в консоль их красиво выводить -- не видел пока.
Крайне интересный видеокурс по созданию динамических оперденей на базе eralng и mnesia:
http://www.erlang-mnesia-video.ru/
Post a Comment