Основы Erlang: синтаксис и пунктуация
Мои теоретичесие рассуждения о месте Erlang в современном мире
Интернете Вы
можете почитать в отдельной статье. Если сомневаетесь интересно Вам это
все или нет — то прочтите сначала её. Сегодня я постараюсь вернуться с
небес на землю и пройтись по азам этого пугающего многих языка
программирования. Коротко и по делу.
Установка ничем особым не выделяется, дистрибутив рекомендую брать
отсюда,
если до сих пор пользуетесь отсутствующей в списке ОС — лучше сначала
исправить этот факт.
После установки в $PATH
окажутся исполняемые файлы:
- erl — одновременно интерактивная консоль и запуск приложений;
- erlc — компилятор в байт-код для виртуальной машины BEAM или
нативный код посредством HiPE, напрямую использовать не придется
практически.
Со всем что будет обсуждаться в этой статье можно эксперементировать
просто в интерактивной консоли, которая запускается просто командой
erl без аргументов.
Пунктуация
Сразу скажу, что пунктуация в Erlang довольно своеобразна, больше похожа
на русский язык, чем на другие языки программирования. По крайней мере я
именно этой ассоциацией пользовался, когда запоминал.
- Все функции заканчиваются точкой
- После каждого выражения в функции — запятая;
- Все ветви кода
(case, if, ...)
, кроме последней, заканчиваются
точкой с запятой - После заголовка функции и условий ветвления пишется стрелка
->
Маленькая демонстрация:
foo(X, Y) -> Z = X * X, if Y > 0 -> Z + Y; true -> Z - Y end.
К слову, функции возвращают результат выполнения последнего выражения, в
данном случае оно представляет собой весь блок if
, а end
обозначает его окончание (не функции).
Синтаксис
Foo
— все что начинается с английской заглавной буквы —
переменная, специально объявлять ничего не нужно_
— сам знак нижнего подчеркивания и все что с него
начинается — особый случай переменной, значение которой не значимо
для программы и при первой возможности «выкидывается»- Цифры в основном как обычно, есть научная нотация в духе
1.23e4
(1.23 умножить на 10 в степени 4) и системы исчисления с другим
основанием, скажем двоичная —2#101010
foo
— с строчной буквы начинаются атомы, по сути константы,
используются повсеместно:- названия функций и модулей
true
иfalse
— булевые значенияok
— типичный результат успешный результат выполнения
?FOO
— хоть официально и называются константами, но по сути —
макросы, перед компиляцией заменяются на заранее определенный кусок
кода{foo, bar}
— кортеж, набор данных фиксированной длины[foo, bar]
— простой однонаправленный список произвольной длины"foo"
— текстовая строка, представленная в виде
однонаправленного списка (что не эффективно с точки зрения
потребления памяти, до 4 байт на символ)<<"foo">>
— бинарная строка, может содержать что угодно,
в.т.ч. и текст; все что не цифры по возможности лучше хранить в этом
типе данных.
Сопоставление (pattern matching)
Очень мощная концепция сопоставления используется в Erlang на
каждом углу. В базовом варианте работает примерно так:
{ok, Result} = foo().
Если в функции foo все прошло нормально, то она возвращает, например
{ok, 123}
, и переменной Result
окажется лишь значение 123
.
Если же возникла какая-то проблема, то она вернет что-то другое, скажем
{error, timeout}
, приложение столкнется с несоответствием левой и
правой части (атомы ok и error разные) и прекращает свое
выполнение (если бы было чего выполнять).
Базовый принцип, надеюсь, понятен. Подобным образом выбирается какую из
реализаций функции использовать, в какую ветвь case идти и т.п. В
общем есть много других более сложных применений, но о них в другой раз.
Списки
Со списками есть три особые операции:
[Head | Tail ] = [1, 2, 3, 4]
— вытащить элемент с головы
списка, работает по принципу сопоставления, вHead
окажется
1
, а вTail
—[2, 3, 4]
[1, 2] ++ [3, 4]
— конкатенация, результатом будет[1, 2, 3, 4]
[N * N || N <- [1, 2, 3], N > 1]
— выглядит замороченно, по
сути это обычный отображение (map) с фильтрацией (filter) — то
есть выражение перед||
применяется к каждому элементу списка,
значение которых попадает в переменную N, а после запятой —
условие, накладываемое на N; таким образом результат будет [4,
9]
Бинарные строки
C ними намного больше всяких трюков и преобразований, приведу наиболее
значимые:
Binary = <<Integer:64>>
— преобразовать целое число Integer
в бинарную строку Binary длиной 64 бита (для примера, может быть
любой<<Integer1:32, Integer2:32>> = Binary
— распокавать обратно
бинарную строку в целые числа, но уже два по 32 бита; чем-то похоже
на операцию[H | T]
у списков, но намного более гибкоBinary3 = <<Binary1/binary, Binary2/binary>>
— конкатенация
бинарных строк, результат окажется вBinary3
<< <<(N * N)/integer>> || <<N>> <= <<1, 2, 3>>, N > 1 >>
— аналог последнего примера для списков, только для
бинарных данных; результат аналогичен —<<4, 9>>
; к слову
официально это называется binary comprehensions, а для списков —
list comprehensions
Заключение
Очень многое пришлось опустить, иначе самое главное затерялось бы, да и
объем статьи сильно вырос. Подробности всегда можно найти на
официальном сайте, в man’ах, да и просто
погуглив.
Удачного освоения Erlang!
Источник: Основы Erlang: синтаксис и пунктуация