erlang.md

Личный сайт Go-разработчика из Казани

1% Символ процента предваряет однострочный комментарий. 2 3%% Два символа процента обычно используются для комментариев к функциям. 4 5%%% Три символа процента используются для комментариев к модулям. 6 7% Пунктуационные знаки, используемые в Erlang: 8% Запятая (`,`) разделяет аргументы в вызовах функций, структурах данных и 9% образцах. 10% Точка (`.`) (с пробелом после неё) разделяет функции и выражения в 11% оболочке. 12% Точка с запятой (`;`) разделяет выражения в следующих контекстах: 13% формулы функций, выражения `case`, `if`, `try..catch` и `receive`. 14 15%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16%% 1. Переменные и сопоставление с образцом. 17%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 19Num = 42. % Все названия переменных начинаются с большой буквы. 20 21% Erlang использует единичное присваивание переменным. Если вы попытаетесь 22% присвоить другое значение переменной `Num`, вы получите ошибку. 23Num = 43. % ** exception error: no match of right hand side value 43 24 25% В большинстве языков `=` обозначает операцию присвоения. В отличие от них, в 26% Erlang `=` — операция сопоставления с образцом. `Lhs = Rhs` на самом 27% деле подразумевает «вычисли правую часть выражения (Rhs) и затем сопоставь 28% результат с образцом слева (Lhs)». 29Num = 7 * 6. 30 31% Числа с плавающей точкой. 32Pi = 3.14159. 33 34% Атомы используются для представления различных нечисловых констант. Названия 35% атомов начинаются с буквы в нижнем регистре, за которой могут следовать другие 36% буквы английского алфавита, цифры, символ подчёркивания (`_`) или «собака» 37% (`@`). 38Hello = hello. 39OtherNode = example@node. 40 41% Если в имени атома нужно использовать другие символы, кроме допустимых, 42% имя атома необходимо взять в одинарные кавычки (`'`). 43AtomWithSpace = 'some atom with space'. 44 45% Кортежы подобны структурам в языке C. 46Point = {point, 10, 45}. 47 48% Если нужно извлечь определённые данные из кортежа, используется оператор 49% сопоставления с образцом — `=`. 50{point, X, Y} = Point. % X = 10, Y = 45 51 52% Символ `_` может использоваться как «заполнитель» для переменных, значения 53% которых в текущем выражении нас не интересуют. Он называется анонимной 54% переменной. В отличие от остальных переменных, множественные использования 55% `_` в одном образце не требуют, чтобы все значения, присваевыемые этой 56% переменной, были идентичными. 57Person = {person, {name, {first, joe}, {last, armstrong}}, {footsize, 42}}. 58{_, {_, {_, Who}, _}, _} = Person. % Who = joe 59 60% Список создаётся путём заключения его элементов в квадратные скобки и 61% разделения их запятыми. Отдельные элементы списка могут быть любого типа. 62% Первый элемент списка называется головой списка. Список, получающийся в 63% результате отделения головы, называется хвостом списка. 64ThingsToBuy = [{apples, 10}, {pears, 6}, {milk, 3}]. 65 66% Если `T` — список, то `[H|T]` — тоже список, где `H` является головой, а `T` — 67% хвостом. Вертикальная черта (`|`) разделяет голову и хвост списка. 68% `[]` — пустой список. 69% Мы можем извлекать элементы из списка с помощью сопоставления с образцом. 70% Если у нас есть непустой список `L`, тогда выражение `[X|Y] = L`, где `X` и 71% `Y` — свободные (не связанные с другими значениям) переменные, извлечёт голову 72% списка в `X` и его хвост в `Y`. 73[FirstThing|OtherThingsToBuy] = ThingsToBuy. 74% FirstThing = {apples, 10} 75% OtherThingsToBuy = {pears, 6}, {milk, 3} 76 77% В Erlang нет строк как отдельного типа. Все используемые в программах строки 78% являются обычным списком целых чисел. Строковые значения всегда должны быть в 79% двойных кавычках (`"`). 80Name = "Hello". 81[72, 101, 108, 108, 111] = "Hello". 82 83 84%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 85%% 2. Последовательное программирование. 86%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 87 88% Модуль — основная единица кода в Erlang. В них пишутся и сохраняются все 89% функции. Модули хранятся в файлах с расширением `.erl`. 90% Модули должны быть скомпилированы перед тем, как использовать код из них. 91% Скомпилированный файл модуля имеет разрешение `.beam`. 92-module(geometry). 93-export([area/1]). % список функций, экспортируемых из модуля. 94 95% Функция `area` состоит из двух формул (clauses). Формулы отделяются друг от 96% друга точкой с запятой, после последнего определения должна стоять точка с 97% пробелом после неё. 98% Каждое определение имеет заголовок и тело. Заголовок состоит из названия 99% функции и образца (в скобках); тело состоит из последовательных выражений, 100% вычисляемых, когда аргументы функции совпадают с образцом в заголовке. 101% Сопоставление с образцами в заголовках происходит в том порядке, в котором 102% они перечислены в определении функции. 103area({rectangle, Width, Ht}) -> Width * Ht; 104area({circle, R}) -> 3.14159 * R * R. 105 106% Компиляция файла с исходным кодом geometry.erl. 107c(geometry). % {ok,geometry} 108 109% Необходимо указывать имя модуля вместе с именем функции для определения, какую 110% именно фукнцию мы хотим вызвать. 111geometry:area({rectangle, 10, 5}). % 50 112geometry:area({circle, 1.4}). % 6.15752 113 114% В Erlang две функции с разной арностью (числом аргументов) в пределах одного 115% модуля представляются как две разные функции. 116-module(lib_misc). 117-export([sum/1]). % экспорт функции `sum` с арностью 1, принимающую один аргумент. 118sum(L) -> sum(L, 0). 119sum([], N) -> N; 120sum([H|T], N) -> sum(T, H+N). 121 122% Fun'ы — анонимные функции, называемые так по причине отсутствия имени. Зато 123% их можно присваивать переменным. 124Double = fun(X) -> 2*X end. % `Double` указывает на анонимную функцию с идентификатором: #Fun<erl_eval.6.17052888> 125Double(2). % 4 126 127% Функции могут принимать fun'ы как параметры и возвращать их в качестве 128% результата вычислений. 129Mult = fun(Times) -> ( fun(X) -> X * Times end ) end. 130Triple = Mult(3). 131Triple(5). % 15 132 133% Выделения списоков (list comprehensions) — выражения, создающие списки без 134% применения анонимных функций, фильтров или map'ов. 135% Запись `[F(X) || X <- L]` значит «список `F(X)`, где `X` последовательно 136% выбирается из списка `L`». 137L = [1,2,3,4,5]. 138[2*X || X <- L]. % [2,4,6,8,10] 139% В выделениях списков могут быть генераторы и фильтры для отделения подмножеств 140% генерируемых значений. 141EvenNumbers = [N || N <- [1, 2, 3, 4], N rem 2 == 0]. % [2, 4] 142 143% Охранные выражения используются для простых проверок переменных в образцах, 144% что значительно расширяет возможности сопоставления. Они могут использоваться 145% в заголовках определений функций, предварённые ключевым словом `when`, а также 146% в условных конструкциях. 147max(X, Y) when X > Y -> X; 148max(X, Y) -> Y. 149 150% Охранные выражения можно группировать, разделяя запятой. 151% Последовательность `GuardExpr1, GuardExpr2, ..., GuardExprN` является истинной 152% только в том случае, когда все выражения, которые она содержат, являются 153% истинными. 154is_cat(A) when is_atom(A), A =:= cat -> true; 155is_cat(A) -> false. 156is_dog(A) when is_atom(A), A =:= dog -> true; 157is_dog(A) -> false. 158 159% Последовательность охранных выражений, разделённых точками с запятой, является 160% истинной в том случае, если хотя бы одно выражение из списка `G1; G2; ...; Gn` 161% является истинным. 162is_pet(A) when is_dog(A); is_cat(A) -> true; 163is_pet(A) -> false. 164 165% Записи предоставляют возможность именования определённых элементов в кортежах. 166% Определения записей могут быть включены в исходный код модулей Erlang или же 167% в заголовочные файлы с расширением `.hrl`. 168-record(todo, { 169 status = reminder, % Значение по умолчанию. 170 who = joe, 171 text 172}). 173 174% Для чтения определений записей из файлов в оболочке можно использовать команду 175% `rr`. 176rr("records.hrl"). % [todo] 177 178% Создание и изменение записей. 179X = #todo{}. 180% #todo{status = reminder, who = joe, text = undefined} 181X1 = #todo{status = urgent, text = "Fix errata in book"}. 182% #todo{status = urgent, who = joe, text = "Fix errata in book"} 183X2 = X1#todo{status = done}. 184% #todo{status = done,who = joe,text = "Fix errata in book"} 185 186% Условное выражение `case`. 187% Функция `filter` возвращет список всех элементов `X` из списка `L`, для 188% которых выражение `P(X)` является истинным. 189filter(P, [H|T]) -> 190 case P(H) of 191 true -> [H|filter(P, T)]; 192 false -> filter(P, T) 193 end; 194filter(P, []) -> []. 195filter(fun(X) -> X rem 2 == 0 end, [1, 2, 3, 4]). % [2, 4] 196 197% Условное выражение `if`. 198max(X, Y) -> 199 if 200 X > Y -> X; 201 X < Y -> Y; 202 true -> nil; 203 end. 204 205% Внимание: в выражении `if` должно быть как минимум одно охранное выраженние, 206% вычисляющееся в true, иначе возникнет исключение. 207 208 209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 210%% 3. Обработка исключений. 211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 212 213% Исключения возникают в случае внутренних ошибок системы или вызываются 214% непосредственно из кода программы с помощью вызовов `throw(Exception)`, 215% `exit(Exception)` или `erlang:error(Exception)`. 216generate_exception(1) -> a; 217generate_exception(2) -> throw(a); 218generate_exception(3) -> exit(a); 219generate_exception(4) -> {'EXIT', a}; 220generate_exception(5) -> erlang:error(a). 221 222% В Erlang есть два способа обработки исключений. Первый заключается в 223% использовании выражения `try..catch` в функции, в которой возможен выброс 224% исключения. 225catcher(N) -> 226 try generate_exception(N) of 227 Val -> {N, normal, Val} 228 catch 229 throw:X -> {N, caught, thrown, X}; 230 exit:X -> {N, caught, exited, X}; 231 error:X -> {N, caught, error, X} 232 end. 233 234% Второй способ заключается в использовании `catch`. Во время поимки исключения 235% оно преобразуется в кортеж с информацией об ошибке. 236catcher(N) -> catch generate_exception(N).

Ссылки: