Spec-Zone.ru › Elixir 1.14

Ядро

Kernel является стандартной средой Elixir.

Она в основном состоит из:

  • базовых языковых примитивов, таких как арифметические операторы, создание процессов, обработка типов данных и другие
  • макросов для управления потоком и определения новой функциональности (модули, функции и т. п.)
  • проверок guard для дополнения сопоставления с образцом

Вы можете вызывать функции и макросы Kernel в любом месте кода Elixir без использования префикса Kernel., так как они все автоматически импортированы. Например, в IEx вы можете вызвать:

iex> is_number(13)
true

Если вы не хотите импортировать функцию или макрос из Kernel, используйте опцию :except и затем перечислите функцию/макрос по арности:

import Kernel, except: [if: 2, unless: 2]

См. Kernel.SpecialForms.import/2 для получения дополнительной информации об импорте.

Elixir также имеет специальные формы, которые всегда импортируются и не могут быть пропущены. Они описаны в Kernel.SpecialForms.

Стандартная библиотека

Kernel предоставляет базовые возможности, на которых построена стандартная библиотека Elixir. Рекомендуется изучить стандартную библиотеку для получения расширенной функциональности. Ниже приведены основные группы модулей в стандартной библиотеке (этот список не является полным справочником, см. колонку документации для всех записей).

Встроенные типы

Следующие модули обрабатывают встроенные типы данных Elixir:

  • Atom - литеральные константы с именем (true, false, и nil — атомы)
  • Float - числа с плавающей точкой
  • Function - ссылка на фрагмент кода, созданный с помощью специальной формы fn/1
  • Integer - целые числа (без дробных частей)
  • List - коллекции переменного количества элементов (связанные списки)
  • Map - коллекции пар ключ-значение
  • Process - лёгкие потоки выполнения
  • Port - механизмы взаимодействия с внешним миром
  • Tuple - коллекции фиксированного количества элементов

Существуют два типа данных без сопровождающего модуля:

  • Битовый массив — последовательность битов, созданная с помощью Kernel.SpecialForms.<<>>/1. Когда количество битов кратно 8, они называются двоичными и могут быть обработаны модулем Erlang :binary
  • Ссылка — уникальное значение в системе выполнения, созданное с помощью make_ref/0

Типы данных

Elixir также предоставляет другие типы данных, основанные на перечисленных выше. Некоторые из них:

  • Date - структуры year-month-day в заданном календаре
  • DateTime - дата и время с часовым поясом в заданном календаре
  • Exception - данные, поднимаемые при ошибках и непредвиденных сценариях
  • MapSet - неупорядоченные коллекции уникальных элементов
  • NaiveDateTime - дата и время без часового пояса в заданном календаре
  • Keyword - списки пар кортежей из двух элементов, часто представляющие необязательные значения
  • Range - включающие диапазоны между двумя целыми числами
  • Regex - регулярные выражения
  • String - двоичные данные кодированные в UTF-8, представляющие символы
  • Time - структуры hour:minute:second в заданном календаре
  • URI - представление URI, идентифицирующих ресурсы
  • Version - представление версий и требований

Системные модули

Модули, взаимодействующие с базовой системой, такие как:

  • IO - обрабатывает ввод и вывод
  • File - взаимодействует с файловой системой
  • Path - манипулирует путями в файловой системе
  • System - считывает и записывает системную информацию

Протоколы

Протоколы добавляют полиморфную обработку в Elixir. Они являются контрактами, реализуемыми типами данных. См. Protocol для получения дополнительной информации о протоколах. В стандартной библиотеке Elixir представлены следующие протоколы:

  • Collectable - собирает данные в тип данных
  • Enumerable - обрабатывает коллекции в Elixir. Модуль Enum предоставляет жадные функции для работы с коллекциями, а модуль Stream — ленивые.
  • Inspect - преобразует типы данных в их представление на языке программирования
  • List.Chars - преобразует типы данных в их представление для внешнего мира в виде списков символов (не базирующееся на программировании)
  • String.Chars - преобразует типы данных в их представление для внешнего мира в виде строк (не базирующееся на программировании)

Функциональность, ориентированная на процессы и приложения

Следующие модули строятся на основе процессов для обеспечения конкурентности, отказоустойчивости и многого другого.

  • Agent - процесс, инкапсулирующий изменяемое состояние
  • Application - функции для запуска, остановки и настройки приложений
  • GenServer - общий API клиент-сервер
  • Registry - хранилище ключ-значение на основе процессов
  • Supervisor - процесс, отвечающий за запуск, контроль и остановку других процессов
  • Task - процесс, выполняющий вычисления
  • Task.Supervisor - supervisor для управления исключительно задачами

Дополнительная документация

Документация Elixir также включает вспомогательные документы в разделе "Страницы". Это:

  • Совместимость и устаревание - перечисляет совместимость между каждой версией Elixir и Erlang/OTP, схему релизов; перечисляет все устаревшие функции, когда они устарели и альтернативы
  • Рекомендации по библиотекам - общие рекомендации, антипаттерны и правила для разработчиков библиотек
  • Правила именования - правила именования для кода Elixir
  • Операторы - перечисляет все операторы Elixir и их приоритеты
  • Шаблоны и гварды - введение в шаблоны, гварды и расширения
  • Справочник синтаксиса - справочник синтаксиса языка
  • Типоспецификации- типы и спецификации функций, включая список типов
  • Синтаксис Unicode - описывает поддержку Unicode в Elixir
  • Написание документации - рекомендации по написанию документации в Elixir

Гварды

Этот модуль содержит встроенные гварды, используемые разработчиками Elixir. Они представляют собой предопределенный набор функций и макросов, которые дополняют сопоставление с образцом, обычно вызываемые после оператора when. Например:

def drive(%User{age: age}) when age >= 16 do
  ...
end

Данный условный оператор будет вызван только если возраст пользователя больше или равен 16. Гварды также поддерживают объединение нескольких условий с and и or. Весь гвард считается истинным, если все выражения гварда примут значение true. Более подробное введение в гварды доступно на странице Шаблоны и гварды.

Структурное сравнение

Функции сравнения в этом модуле выполняют структурное сравнение. Это означает, что структуры сравниваются на основе их представления, а не на их семантическом значении. Это особенно важно для функций, предназначенных для предоставления упорядочивания, таких как >/2, </2, >=/2, <=/2, min/2 и max/2. Например:

~D[2017-03-31] > ~D[2017-04-01]

вернёт true, потому что структурное сравнение сравнивает поле :day до :month или :year. Поэтому при сравнении структур часто используется функция compare/2, предоставляемая самими модулями структур:

iex> Date.compare(~D[2017-03-31], ~D[2017-04-01])
:lt

В качестве альтернативы вы можете использовать функции модуля Enum для сортировки или вычисления максимума/минимума:

iex> Enum.sort([~D[2017-03-31], ~D[2017-04-01]], Date)
[~D[2017-03-31], ~D[2017-04-01]]
iex> Enum.max([~D[2017-03-31], ~D[2017-04-01]], Date)
~D[2017-04-01]

Истинностные и ложные значения

Помимо булевых значений true и false, Elixir имеет понятие "истинностного" или "ложного" значения.

  • Значение истинно, когда оно не false и не nil
  • Значение ложно, когда оно либо false, либо nil

Elixir имеет функции, такие как and/2, которые работают только с булевыми значениями, но также функции, которые работают с этими истинностными/ложными значениями, такие как &&/2 и !/1.

Примеры

Мы можем проверить истинность значения, дважды используя функцию !/1.

Истинностные значения:

iex> !!true
true
iex> !!5
true
iex> !![1,2]
true
iex> !!"foo"
true
END_OF_DOCUMENT_MARKER

Ложные значения (их ровно два):

iex> !!false
false
iex> !!nil
false

Инлайнирование

Некоторые из функций, описанных в этом модуле, встроенные в компиляторе Elixir в их аналоги на Erlang в модуле :erlang. Эти функции называются BIF (встроенные внутренние функции) в Erlang и они обладают интересными свойствами, так как некоторые из них разрешены в охраняющих условиях, а другие используются для оптимизации компилятора.

Большинство встроенных функций можно увидеть в действии при захвате функции:

iex> &Kernel.is_atom/1
&:erlang.is_atom/1

Эти функции будут явно помечены в их документации как "встроенные компилятором".

Краткое описание

Охраняющие условия

left * right

Оператор умножения.

+value

Унарный оператор сложения.

left + right

Оператор сложения.

-value

Унарный оператор вычитания.

left - right

Оператор вычитания.

left / right

Оператор деления.

left != right

Оператор неравенства.

left !== right

Оператор строгого неравенства.

left < right

Оператор меньше.

left <= right

Оператор меньше или равно.

left == right

Оператор равенства. Возвращает true если два значения равны.

left === right

Оператор строгого равенства.

left > right

Оператор больше.

left >= right

Оператор больше или равно.

abs(number)

Возвращает целое или вещественное число, являющееся абсолютным значением number.

left and right

Оператор строгой логической "и".

binary_part(binary, start, length)

Извлекает часть бинарного значения, начиная с start длиной length. Бинарные значения нумеруются с нуля.

bit_size(bitstring)

Возвращает целое число, являющееся размером bitstring в битах.

byte_size(bitstring)

Возвращает количество байт, необходимое для хранения bitstring.

ceil(number)

Возвращает наименьшее целое число, большее или равное number.

div(dividend, divisor)

Выполняет целочисленное деление.

elem(tuple, index)

Возвращает элемент по нулевому индексу index в tuple.

floor(number)

Возвращает наибольшее целое число, меньшее или равное number.

hd(list)

Возвращает голову списка. Вызывает ArgumentError если список пустой.

left in right

Оператор принадлежности.

is_atom(term)

Возвращает true если term это атом; в противном случае возвращает false.

is_binary(term)

Возвращает true если term это бинарное значение; в противном случае возвращает false.

is_bitstring(term)

Возвращает true если term это битовая строка (включая бинарное значение); в противном случае возвращает false.

is_boolean(term)

Возвращает true если term это атом true или атом false (т.е. логическое значение); в противном случае возвращает false.

is_exception(term)

Возвращает true, если term является исключением; в противном случае возвращает false.

is_exception(term, name)

Возвращает true, если term является исключением типа name; в противном случае возвращает false.

is_float(term)

Возвращает true если term это число с плавающей точкой; в противном случае возвращает false.

is_function(term)

Возвращает true если term это функция; в противном случае возвращает false.

is_function(term, arity)

Возвращает true если term это функция, которая может быть применена с arity аргументами; в противном случае возвращает false.

is_integer(term)

Возвращает true если term это целое число; в противном случае возвращает false.

is_list(term)

Возвращает true если term это список с нулем или более элементами; в противном случае возвращает false.

is_map(term)

Возвращает true если term это карта; в противном случае возвращает false.

is_map_key(map, key)

Возвращает true если key это ключ в map; в противном случае возвращает false.

is_nil(term)

Возвращает true если term это nil; false в противном случае.

is_number(term)

Возвращает true если term это целое или вещественное число; в противном случае возвращает false.

is_pid(term)

Возвращает true если term это PID (идентификатор процесса); в противном случае возвращает false.

is_port(term)

Возвращает true если term это идентификатор порта; в противном случае возвращает false.

is_reference(term)

Возвращает true если term это ссылка; в противном случае возвращает false.

is_struct(term)

Возвращает true, если term это структура; в противном случае возвращает false.

is_struct(term, name)

Возвращает true, если term это структура типа name; в противном случае возвращает false.

is_tuple(term)

Возвращает true, если term это кортеж; в противном случае возвращает false.

END_OF_DOCUMENT_MARKER
length(list)

Возвращает длину списка.

map_size(map)

Возвращает размер карты.

node()

Возвращает атом, представляющий имя локального узла. Если узел не активен, вместо этого возвращается 0..-1//1.

node(arg)

Возвращает узел, где находится заданный аргумент. Аргумент может быть PID, ссылкой или портом. Если локальный узел не активен, возвращается first.

not value

Строго булевый оператор "not".

left or right

Строго булевый оператор "or".

rem(dividend, divisor)

Вычисляет остаток от целочисленного деления.

round(number)

Округляет число до ближайшего целого.

self()

Возвращает PID (идентификатор процесса) вызывающего процесса.

tl(list)

Возвращает хвост списка. Вызывает ArgumentError, если список пуст.

trunc(number)

Возвращает целую часть числа.

tuple_size(tuple)

Возвращает размер кортежа.

Функции

left && right

Булевый оператор "и".

base ** exponent

Оператор возведения в степень.

left ++ right

Оператор конкатенации списков. Конкатенирует список справа и элемент слева, возвращая список.

left -- right

Оператор вычитания списков. Удаляет первое вхождение элемента справа из списка слева для каждого элемента справа.

..

Создаёт диапазон срезов 0..-1//1.

first..last

Создаёт диапазон от first до last.

first..last//step

Создаёт диапазон от first до last с шагом step.

!value

Булевый оператор "не".

left <> right

Оператор бинарной конкатенации. Конкатенирует два бинарных числа.

left =~ right

Оператор соответствия по тексту. Сопоставляет термин слева с регулярным выражением или строкой справа.

@expr

Унарный оператор атрибута модуля.

alias!(alias)

Когда используется внутри кавычек, отмечает, что данный псевдоним не должен быть санизирован. Это означает, что псевдоним будет расширен при расширении макроса.

apply(fun, args)

Вызывает заданную анонимную функцию fun со списком аргументов args.

apply(module, function_name, args)

Вызывает заданную функцию из module со списком аргументов args.

binary_slice(binary, range)

Возвращает бинарное значение с позиции начала диапазона до позиции конца диапазона.

binary_slice(binary, start, size)

Возвращает бинарное значение, начиная с позиции start и заданного размера size.

binding(context \\ nil)

Возвращает привязку для данного контекста в виде списка ключевых слов.

dbg(code \\ quote do binding() end, options \\ [])

Отлаживает заданный code.

def(call, expr \\ nil)

Определяет публичную функцию с заданным именем и телом.

defdelegate(funs, opts)

Определяет функцию, которая делегирует вызов другому модулю.

defexception(fields)

Определяет исключение.

defguard(guard)

Генерирует макрос, подходящий для использования в выражениях фильтров.

defguardp(guard)

Генерирует частный макрос, подходящий для использования в выражениях фильтров.

defimpl(name, opts, do_block \\ [])

Определяет реализацию для данного протокола.

defmacro(call, expr \\ nil)

Определяет публичный макрос с заданным именем и телом.

defmacrop(call, expr \\ nil)

Определяет частный макрос с заданным именем и телом.

defmodule(alias, do_block)

Определяет модуль по имени с заданным содержимым.

defoverridable(keywords_or_behaviour)

Делает заданные определения в текущем модуле переопределяемыми.

defp(call, expr \\ nil)

Определяет закрытую функцию с заданным именем и телом.

defprotocol(name, do_block)

Определяет протокол.

defstruct(fields)

Определяет структуру.

destructure(left, right)

Деструктурирует два списка, присваивая каждый элемент справа соответствующему элементу слева.

exit(reason)

Прекращает выполнение вызывающего процесса с указанным основанием.

function_exported?(module, function, arity)

Возвращает true, если module загружен и содержит публичную function с заданной arity, в противном случае false.

get_and_update_in(path, fun)

Получает значение и обновляет вложенную структуру данных с помощью заданной path.

get_and_update_in(data, keys, fun)

Получает значение и обновляет вложенную структуру данных.

get_in(data, keys)

Получает значение из вложенной структуры.

if(condition, clauses)

Предоставляет макрос if/2.

inspect(term, opts \\ [])

Отображает заданный аргумент в соответствии с протоколом Inspect. Второй аргумент — список ключевых слов с опциями для управления отображением.

macro_exported?(module, macro, arity)

Возвращает true, если module загружен и содержит публичный macro с заданной arity, в противном случае false.

make_ref()

Возвращает почти уникальную ссылку.

match?(pattern, expr)

Удобный макрос, проверяющий, соответствует ли правая часть (выражение) левой части (шаблону).

max(first, second)

Возвращает наибольший из двух заданных терминов в соответствии с их структурным сравнением.

min(first, second)

Возвращает наименьший из двух заданных терминов в соответствии с их структурным сравнением.

pop_in(path)

Удаляет ключ из вложенной структуры по заданному path.

pop_in(data, keys)

Удаляет ключ из данной вложенной структуры.

put_elem(tuple, index, value)

Заменяет значение value на заданную позицию с нулевой базой index в кортеже tuple.

END_OF_DOCUMENT_MARKER
put_in(path, value)

Размещает значение во вложенной структуре по заданному пути.

put_in(data, keys, value)

Размещает значение во вложенную структуру.

raise(message)

Вызывает исключение.

raise(exception, attributes)

Вызывает исключение.

reraise(message, stacktrace)

Вызывает исключение, сохраняя предыдущий стек вызовов.

reraise(exception, attributes, stacktrace)

Вызывает исключение, сохраняя предыдущий стек вызовов.

send(dest, message)

Отправляет сообщение заданному объекту и возвращает полученное сообщение.

sigil_C(term, modifiers)

Обрабатывает сигил для списков символов.

sigil_c(term, modifiers)

Обрабатывает сигил для списков символов.

sigil_D(date_string, modifiers)

Обрабатывает сигил для дат.

sigil_N(naive_datetime_string, modifiers)

Обрабатывает сигил для неявных дат и времени.

sigil_R(term, modifiers)

Обрабатывает сигил для регулярных выражений.

sigil_r(term, modifiers)

Обрабатывает сигил для регулярных выражений.

sigil_S(term, modifiers)

Обрабатывает сигил для строк.

sigil_s(term, modifiers)

Обрабатывает сигил для строк.

sigil_T(time_string, modifiers)

Обрабатывает сигил для временных значений.

sigil_U(datetime_string, modifiers)

Обрабатывает сигил для создания UTC даты и времени.

sigil_W(term, modifiers)

Обрабатывает сигил для списков слов.

sigil_w(term, modifiers)

Обрабатывает сигил для списков слов.

spawn(fun)

Запускает заданную функцию и возвращает её PID.

spawn(module, fun, args)

Запускает заданную функцию из заданного модуля, передавая ей заданные аргументы, и возвращает её PID.

spawn_link(fun)

Запускает заданную функцию, связывая её с текущим процессом, и возвращает её PID.

spawn_link(module, fun, args)

Запускает заданную функцию из заданного модуля, передавая ей заданные аргументы, связывая её с текущим процессом, и возвращает её PID.

spawn_monitor(fun)

Запускает заданную функцию, отслеживает её и возвращает её PID и ссылку на мониторинг.

spawn_monitor(module, fun, args)

Запускает заданный модуль и функцию, передавая заданные аргументы, отслеживает её и возвращает её PID и ссылку на мониторинг.

struct(struct, fields \\ [])

Создаёт и обновляет структуру.

struct!(struct, fields \\ [])

Аналогично struct/2, но проверяет корректность ключей.

tap(value, fun)

Перенаправляет первый аргумент во второй аргумент, функцию, и возвращает первый аргумент само по себе.

then(value, fun)

Перенаправляет первый аргумент во второй аргумент, функцию, и возвращает результат вызова функции.

throw(term)

Нелокальный возврат из функции.

to_charlist(term)

Преобразует заданный термин в список символов в соответствии с протоколом списка символов.

to_string(term)

Преобразует аргумент в строку в соответствии с протоколом строк.

unless(condition, clauses)

Предоставляет макрос для выполнения кода только если условие ложно.

update_in(path, fun)

Обновляет вложенную структуру по заданному пути.

update_in(data, keys, fun)

Обновляет ключ во вложенной структуре.

use(module, opts \\ [])

Использует заданный модуль в текущем контексте.

var!(var, context \\ nil)

Отмечает, что заданная переменная не должна быть гигиенизирована.

left |> right

Оператор конвейера.

left || right

Булевый оператор "или".

END_OF_DOCUMENT_MARKER

Операторы

left * rightSource

@spec integer() * integer() :: integer()
@spec float() * float() :: float()
@spec integer() * float() :: float()
@spec float() * integer() :: float()

Оператор умножения.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 * 2
2

+valueSource

@spec +integer() :: integer()
@spec +float() :: float()

Унарный оператор положительного числа.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> +1
1

left + rightSource

@spec integer() + integer() :: integer()
@spec float() + float() :: float()
@spec integer() + float() :: float()
@spec float() + integer() :: float()

Оператор сложения.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 + 2
3

-valueSource

@spec -0 :: 0
@spec -pos_integer() :: neg_integer()
@spec -neg_integer() :: pos_integer()
@spec -float() :: float()

Унарный оператор отрицательного числа.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> -2
-2

left - rightSource

@spec integer() - integer() :: integer()
@spec float() - float() :: float()
@spec integer() - float() :: float()
@spec float() - integer() :: float()

Оператор вычитания.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 - 2
-1

left / rightSource

@spec number() / number() :: float()

Оператор деления.

Результат всегда является числом с плавающей точкой. Используйте div/2 и rem/2 для целочисленного деления или остатка.

Вызывает исключение ArithmeticError, если right равно 0 или 0.0.

Разрешен в проверках условий. Встроен компилятором.

Примеры

1 / 2
#=> 0.5

-3.0 / 2.0
#=> -1.5

5 / 1
#=> 5.0

7 / 0
** (ArithmeticError) bad argument in arithmetic expression

left != rightSource

@spec term() != term() :: boolean()

Оператор неравенства.

Возвращает true, если два значения не равны.

Этот оператор считает 1 и 1.0 равными. Для сравнения в соответствии с шаблоном используйте !==/2.

Все значения в Elixir могут быть сравнены друг с другом.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 != 2
true

iex> 1 != 1.0
false

left !== rightSource

@spec term() !== term() :: boolean()

Оператор строгого неравенства.

Возвращает true, если два значения не строго равны. См. ===/2 для определения того, что считается "строго равным".

Все значения в Elixir могут быть сравнены друг с другом.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 !== 2
true

iex> 1 !== 1.0
true

left < rightSource

@spec term() < term() :: boolean()

Оператор меньше.

Возвращает true, если left меньше right.

Выполняется структурное сравнение, где все значения Elixir могут быть сравнены друг с другом. Дополнительную информацию см. в разделе "Структурное сравнение".

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 < 2
true

left <= rightSource

@spec term() <= term() :: boolean()

Оператор меньше или равно.

Возвращает true, если left меньше или равно right.

Выполняется структурное сравнение, где все значения Elixir могут быть сравнены друг с другом. Дополнительную информацию см. в разделе "Структурное сравнение".

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 <= 2
true

left == rightSource

@spec term() == term() :: boolean()

Оператор равенства. Возвращает true, если два значения равны.

Этот оператор считает 1 и 1.0 равными. Для более строгого сравнения используйте ===/2.

Все значения в Elixir могут быть сравнены друг с другом.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 == 2
false

iex> 1 == 1.0
true

left === rightSource

@spec term() === term() :: boolean()

Оператор строгого равенства.

Возвращает true, если два значения строго равны.

Значения считаются строго равными только если они имеют одинаковое значение и тип. Например, 1 == 1.0 возвращает true, но так как они имеют разные типы, 1 === 1.0 возвращает false.

Все значения в Elixir могут быть сравнены друг с другом.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 === 2
false

iex> 1 === 1.0
false

left > rightSource

@spec term() > term() :: boolean()

Оператор больше.

Возвращает true, если left больше right.

Выполняется структурное сравнение, где все значения Elixir могут быть сравнены друг с другом. Дополнительную информацию см. в разделе "Структурное сравнение".

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 > 2
false

left >= rightSource

@spec term() >= term() :: boolean()

Оператор больше или равно.

Возвращает true, если left больше или равно right.

Выполняется структурное сравнение, где все значения Elixir могут быть сравнены друг с другом. Дополнительную информацию см. в разделе "Структурное сравнение".

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> 1 >= 2
false

abs(number)Source

@spec abs(number()) :: number()

Возвращает целое или число с плавающей точкой, которое является абсолютным значением number.

Разрешен в проверках условий. Встроен компилятором.

Примеры

iex> abs(-3.33)
3.33

iex> abs(-3)
3

left and rightSource

Оператор логического "и".

Если left равно true, возвращает right; в противном случае возвращает false.

Требуется, чтобы только операнд right был булевым, так как оператор выполняется по принципу короткого замыкания. Если операнд left не является булевым, возникает исключение BadBooleanError.

Разрешен в проверках условий.

Примеры

iex> true and false
false

iex> true and "yay!"
"yay!"

iex> "yay!" and true
** (BadBooleanError) expected a boolean on left-side of "and", got: "yay!"
END_OF_DOCUMENT_MARKER

binary_part(binary, start, length)Source

@spec binary_part(binary(), non_neg_integer(), integer()) :: binary()

Извлекает часть двоичной строки, начиная с позиции start длиной length. Двоичные строки индексируются с нуля.

Если позиция start или длина length ссылаются на область за пределами двоичной строки, генерируется исключение ArgumentError.

Разрешено в проверках условий. Встраивается компилятором.

Примеры

iex> binary_part("foo", 1, 2)
"oo"

Отрицательная позиция может использоваться для извлечения байтов, которые находятся перед байтом по индексу start:

iex> binary_part("Hello", 5, -3)
"llo"

Исключение ArgumentError генерируется, когда длина выходит за пределы двоичной строки:

binary_part("Hello", 0, 10)
** (ArgumentError) argument error

bit_size(bitstring)Source

@spec bit_size(bitstring()) :: non_neg_integer()

Возвращает целое число, которое представляет размер битовой строки в битах.

Разрешено в проверках условий. Встраивается компилятором.

Примеры

iex> bit_size(<<433::16, 3::3>>)
19

iex> bit_size(<<1, 2, 3>>)
24

byte_size(bitstring)Source

@spec byte_size(bitstring()) :: non_neg_integer()

Возвращает количество байтов, необходимых для хранения битовой строки.

То есть, если количество битов в битовой строке не делится на 8, результат будет округлён вверх (до ближайшего большего целого). Эта операция выполняется за постоянное время.

Разрешено в проверках условий. Встраивается компилятором.

Примеры

iex> byte_size(<<433::16, 3::3>>)
3

iex> byte_size(<<1, 2, 3>>)
3

ceil(number)Source

@spec ceil(number()) :: integer()

Возвращает наименьшее целое число, большее или равное заданному числу.

Если нужно выполнить операцию округления вверх для других десятичных знаков, используйте Float.ceil/2.

Разрешено в проверках условий. Встраивается компилятором.

div(dividend, divisor)Source

@spec div(integer(), neg_integer() | pos_integer()) :: integer()

Выполняет целочисленное деление.

Генерирует исключение ArithmeticError, если один из аргументов не является целым числом или когда делитель равен нулю.

div/2 выполняет обрезанное целочисленное деление. Это означает, что результат всегда округляется к нулю.

Если нужно выполнить целочисленное деление с округлением к меньшему целому (к отрицательной бесконечности), используйте Integer.floor_div/2.

Разрешено в проверках условий. Встраивается компилятором.

Примеры

div(5, 2)
#=> 2

div(6, -4)
#=> -1

div(-99, 2)
#=> -49

div(100, 0)
** (ArithmeticError) bad argument in arithmetic expression

elem(tuple, index)Source

@spec elem(tuple(), non_neg_integer()) :: term()

Возвращает элемент по указанному индексу в кортеже.

Генерирует ArgumentError, если индекс отрицательный или выходит за пределы элементов кортежа.

Разрешено в проверках условий. Встраивается компилятором.

Примеры

tuple = {:foo, :bar, 3}
elem(tuple, 1)
#=> :bar

elem({}, 0)
** (ArgumentError) argument error

elem({:foo, :bar}, 2)
** (ArgumentError) argument error

floor(number)Source

@spec floor(number()) :: integer()

Возвращает наибольшее целое число, меньшее или равное заданному числу.

Если нужно выполнить операцию округления вниз для других десятичных знаков, используйте Float.floor/2.

Разрешено в проверках условий. Встраивается компилятором.

hd(list)Source

@spec hd(nonempty_maybe_improper_list(elem, any())) :: elem when elem: term()

Возвращает голову списка. Генерирует ArgumentError, если список пустой.

Голова списка — это его первый элемент.

Работает со списками, которые не являются собственными списками (improper lists).

Разрешено в проверках условий. Встраивается компилятором.

Примеры

hd([1, 2, 3, 4])
#=> 1

hd([1 | 2])
#=> 1

Для пустого списка генерируется исключение:

hd([])
#=> ** (ArgumentError) argument error

left in rightSource

Оператор принадлежности.

Проверяет, является ли элемент слева членом коллекции справа.

Примеры

iex> x = 1
iex> x in [1, 2, 3]
true

Этот оператор (который является макросом) просто преобразуется в вызов Enum.member?/2. Приведённый выше пример преобразуется в:

Enum.member?([1, 2, 3], x)

Elixir также поддерживает left not in right, что эквивалентно not(left in right):

iex> x = 1
iex> x not in [1, 2, 3]
false

Условия

Оператор in/2 (а также not in) может использоваться в условиях, если правая часть — это диапазон или список.

Если правая часть — список, Elixir преобразует оператор в выражение условия, которое должно проверить каждый элемент списка. Например:

when x in [1, 2, 3]

преобразуется в:

when x === 1 or x === 2 or x === 3

Однако, такая конструкция будет неэффективной для больших списков. В таких случаях лучше отказаться от условий и использовать более подходящую структуру данных, например, MapSet.

Если правая часть — диапазон, будет выполнена более эффективная проверка. Например:

when x in 1..1000

приблизительно преобразуется в:

when x >= 1 and x <= 1000

Учёт AST

left not in right анализируется компилятором в AST:

{:not, _, [{:in, _, [left, right]}]}

Это тот же AST, что и not(left in right).

Кроме того, Macro.to_string/2 и Code.format_string!/2 преобразуют все вхождения этого AST в left not in right.

is_atom(term)Source

@spec is_atom(term()) :: boolean()

Возвращает `true`, если `term` является атомом; иначе возвращает `false`.

Разрешено в проверках условий. Встраивается компилятором.

Примеры

iex> is_atom(false)
true

iex> is_atom(:name)
true

iex> is_atom(AnAtom)
true

iex> is_atom("true")
false

is_binary(term)Source

@spec is_binary(term()) :: boolean()

Возвращает `true`, если `term` является двоичной строкой; иначе возвращает `false`.

Двоичная строка всегда содержит полное количество байтов.

Разрешено в проверках условий. Встраивается компилятором.

Примеры

iex> is_binary("foo")
true
iex> is_binary(<<1::3>>)
false

is_bitstring(term)Source

@spec is_bitstring(term()) :: boolean()

Возвращает `true`, если `term` является битовой строкой (включая двоичную строку); иначе возвращает `false`.

Разрешено в проверках условий. Встраивается компилятором.

Примеры

iex> is_bitstring("foo")
true
iex> is_bitstring(<<1::3>>)
true

is_boolean(term)Source

@spec is_boolean(term()) :: boolean()

Возвращает `true`, если `term` является либо атомом `true`, либо атомом `false` (то есть, булевым значением); иначе возвращает `false`.

Разрешено в проверках условий. Встраивается компилятором.

Примеры

iex> is_boolean(false)
true

iex> is_boolean(true)
true

iex> is_boolean(:test)
false

is_exception(term)Source

Возвращает `true`, если `term` является исключением; иначе возвращает `false`.

Разрешено в проверках условий.

Примеры

iex> is_exception(%RuntimeError{})
true

iex> is_exception(%{})
false
END_OF_DOCUMENT_MARKER

is_exception(term, name)Source

Возвращает true, если term является исключением типа name; иначе возвращает false.

Разрешено в проверках условий.

Примеры

iex> is_exception(%RuntimeError{}, RuntimeError)
true

iex> is_exception(%RuntimeError{}, Macro.Env)
false
END_OF_DOCUMENT_MARKER

is_float(term)Source

@spec is_float(term()) :: boolean()

Возвращает true, если term является числом с плавающей точкой; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

is_function(term)Source

@spec is_function(term()) :: boolean()

Возвращает true, если term является функцией; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

Примеры

iex> is_function(fn x -> x + x end)
true

iex> is_function("not a function")
false

is_function(term, arity)Source

@spec is_function(term(), non_neg_integer()) :: boolean()

Возвращает true, если term является функцией, которая может быть применена с arity количеством аргументов; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

Примеры

iex> is_function(fn x -> x * 2 end, 1)
true
iex> is_function(fn x -> x * 2 end, 2)
false

is_integer(term)Source

@spec is_integer(term()) :: boolean()

Возвращает true, если term является целым числом; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

is_list(term)Source

@spec is_list(term()) :: boolean()

Возвращает true, если term является списком с нулём или более элементами; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

is_map(term)Source

@spec is_map(term()) :: boolean()

Возвращает true, если term является картой; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

is_map_key(map, key)Source

@spec is_map_key(map(), term()) :: boolean()

Возвращает true, если key является ключом в map; в противном случае возвращает false.

Вызывает BadMapError, если первый элемент не является картой.

Разрешено в тестах стражей. Встраивается компилятором.

is_nil(term)Source

Возвращает true, если term является nil, false в противном случае.

Разрешено в выражениях стражей.

Примеры

iex> is_nil(1)
false

iex> is_nil(nil)
true

is_number(term)Source

@spec is_number(term()) :: boolean()

Возвращает true, если term является либо целым числом, либо числом с плавающей точкой; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

is_pid(term)Source

@spec is_pid(term()) :: boolean()

Возвращает true, если term является PID (идентификатор процесса); в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

is_port(term)Source

@spec is_port(term()) :: boolean()

Возвращает true, если term является идентификатором порта; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

is_reference(term)Source

@spec is_reference(term()) :: boolean()

Возвращает true, если term является ссылкой; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

is_struct(term)Source

Возвращает true, если term является структурой; в противном случае возвращает false.

Разрешено в тестах стражей.

Примеры

iex> is_struct(URI.parse("/"))
true

iex> is_struct(%{})
false

is_struct(term, name)Source

Возвращает true, если term является структурой name; в противном случае возвращает false.

Разрешено в тестах стражей.

Примеры

iex> is_struct(URI.parse("/"), URI)
true

iex> is_struct(URI.parse("/"), Macro.Env)
false

is_tuple(term)Source

@spec is_tuple(term()) :: boolean()

Возвращает true, если term является кортежем; в противном случае возвращает false.

Разрешено в тестах стражей. Встраивается компилятором.

length(list)Source

@spec length(list()) :: non_neg_integer()

Возвращает длину list.

Разрешено в тестах стражей. Встраивается компилятором.

Примеры

iex> length([1, 2, 3, 4, 5, 6, 7, 8, 9])
9

map_size(map)Source

@spec map_size(map()) :: non_neg_integer()

Возвращает размер карты.

Размер карты — это количество пар ключ-значение, которые содержит карта.

Эта операция выполняется за константное время.

Разрешено в тестах стражей. Встраивается компилятором.

Примеры

iex> map_size(%{a: "foo", b: "bar"})
2

node()Source

@spec node() :: node()

Возвращает атом, представляющий имя локального узла. Если узел не активен, вместо этого возвращается :erlang.node().

Разрешено в тестах стражей. Встраивается компилятором.

node(arg)Source

@spec node(pid() | reference() | port()) :: node()

Возвращает узел, где находится данный аргумент. Аргументом может быть PID, ссылка или порт. Если локальный узел не активен, возвращается :erlang.node().

Разрешено в тестах стражей. Встраивается компилятором.

not valueSource

@spec not true :: false
@spec not false :: true

Оператор строгой логической инверсии.

value должен быть булевым; если это не так, генерируется исключение ArgumentError.

Разрешено в тестах стражей. Встраивается компилятором.

Примеры

iex> not false
true
END_OF_DOCUMENT_MARKER

left or rightSource

Оператор строгой логической дизъюнкции.

Если left является true, возвращает true; в противном случае возвращает right.

Требуется, чтобы только left операнд был булевым, поскольку он выполняется по принципу короткого замыкания. Если left операнд не является булевым, генерируется исключение BadBooleanError.

Разрешено в тестах стражей.

Примеры

iex> true or false
true

iex> false or 42
42

iex> 42 or false
** (BadBooleanError) expected a boolean on left-side of "or", got: 42
END_OF_DOCUMENT_MARKER

rem(делимое, делитель)Source

@spec rem(integer(), neg_integer() | pos_integer()) :: integer()

Вычисляет остаток от деления целых чисел.

rem/2 использует усечение при делении, что означает, что результат всегда будет иметь знак dividend.

Вызывает исключение ArithmeticError, если один из аргументов не является целым числом или когда divisor является 0.

Разрешено в тестах условий. Встроен компилятором.

Примеры

iex> rem(5, 2)
1
iex> rem(6, -4)
2

round(число)Source

@spec round(number()) :: integer()

Округляет число до ближайшего целого.

Если число равноудалено от двух ближайших целых чисел, округляет от нуля.

Разрешено в тестах условий. Встроен компилятором.

Примеры

iex> round(5.6)
6

iex> round(5.2)
5

iex> round(-9.9)
-10

iex> round(-9)
-9

iex> round(2.5)
3

iex> round(-2.5)
-3

self()Source

@spec self() :: pid()

Возвращает PID (идентификатор процесса) вызывающего процесса.

Разрешено в условиях. Встроен компилятором.

tl(список)Source

@spec tl(nonempty_maybe_improper_list(elem, last)) ::
  maybe_improper_list(elem, last) | last
when elem: term(), last: term()

Возвращает хвост списка. Вызывает ArgumentError, если список пуст.

Хвостом списка является список без его первого элемента.

Работает со списками неправильной структуры.

Разрешено в тестах условий. Встроен компилятором.

Примеры

tl([1, 2, 3, :go])
#=> [2, 3, :go]

tl([:one])
#=> []

tl([:a, :b | :improper_end])
#=> [:b | :improper_end]

tl([:a | %{b: 1}])
#=> %{b: 1}

Передача пустого списка вызывает:

tl([])
#=> ** (ArgumentError) argument error

trunc(число)Source

@spec trunc(number()) :: integer()

Возвращает целую часть number.

Разрешено в тестах условий. Встроен компилятором.

Примеры

iex> trunc(5.4)
5

iex> trunc(-5.99)
-5

iex> trunc(-5)
-5

tuple_size(кортеж)Source

@spec tuple_size(tuple()) :: non_neg_integer()

Возвращает размер кортежа.

Эта операция выполняется за постоянное время.

Разрешено в тестах условий. Встроен компилятором.

Примеры

iex> tuple_size({:a, :b, :c})
3

Функции

left && rightSource

Логический оператор "и".

Обеспечивает оператор короткого замыкания, который оценивает и возвращает второе выражение только в том случае, если первое выражение оценивается как истинное значение (ни false ни nil). В противном случае возвращает первое выражение.

Запрещено в условиях защиты.

Примеры

iex> Enum.empty?([]) && Enum.empty?([])
true

iex> List.first([]) && true
nil

iex> Enum.empty?([]) && List.first([1])
1

iex> false && throw(:bad)
false

Обратите внимание, что в отличие от and/2, этот оператор принимает любое выражение в качестве первого аргумента, а не только булевы значения.

base ** exponentSource

@spec integer() ** non_neg_integer() :: integer()
@spec integer() ** neg_integer() :: float()
@spec float() ** float() :: float()

Оператор возведения в степень.

Ожидает два числовых входных значения. Если левая часть — целое число, а правая — неотрицательное число, результат — целое число. В противном случае возвращается число с плавающей точкой.

Примеры

iex> 2 ** 2
4
iex> 2 ** -4
0.0625

iex> 2.0 ** 2
4.0
iex> 2 ** 2.0
4.0

left ++ rightSource

@spec list() ++ term() :: maybe_improper_list()

Оператор конкатенации списков. Объединяет правильный список и элемент, возвращая список.

Сложность a ++ b пропорциональна length(a), поэтому избегайте многократного добавления в списки произвольной длины, например, list ++ [element]. Вместо этого рассмотрите возможность добавления в начало посредством [element | rest] и последующего реверсирования.

Если операнд right не является правильным списком, возвращается неправильный список. Если операнд left не является правильным списком, генерируется исключение ArgumentError.

Встраивается компилятором.

Примеры

iex> [1] ++ [2, 3]
[1, 2, 3]

iex> 'foo' ++ 'bar'
'foobar'

# returns an improper list
iex> [1] ++ 2
[1 | 2]

# returns a proper list
iex> [1] ++ [2]
[1, 2]

# improper list on the right will return an improper list
iex> [1] ++ [2 | 3]
[1, 2 | 3]

left -- rightSource

@spec list() -- list() :: list()

Оператор вычитания списков. Удаляет первое вхождение элемента из левого списка для каждого элемента справа.

Функция оптимизирована, поэтому сложность a -- b пропорциональна length(a) * log(length(b)). См. также руководство по эффективности Erlang.

Встраивается компилятором.

Примеры

iex> [1, 2, 3] -- [1, 2]
[3]

iex> [1, 2, 3, 2, 1] -- [1, 2, 2]
[3, 1]

Оператор --/2 является правоассоциативным, что означает:

iex> [1, 2, 3] -- [2] -- [3]
[1, 3]

Что эквивалентно:

iex> [1, 2, 3] -- ([2] -- [3])
[1, 3]

..Source

Создаёт полный диапазон слайсов 0..-1//1.

Этот макрос возвращает диапазон со следующими свойствами:

  • При перечислении он пуст

  • При использовании как slice, возвращает срезанный элемент как есть

См. ..///3 и модуль Range для получения дополнительной информации.

Примеры

iex> Enum.to_list(..)
[]

iex> String.slice("Hello world!", ..)
"Hello world!"

first..lastSource

Создаёт диапазон от first до last.

Если first меньше last, диапазон будет возрастать от first до last. Если first равно last, диапазон будет содержать один элемент — само число.

Если first больше last, диапазон будет убывать от first до last, хотя это поведение устарело. Вместо этого предпочтительнее явно указать шаг с first..last//-1.

См. модуль Range для получения дополнительной информации.

Примеры

iex> 0 in 1..3
false
iex> 2 in 1..3
true

iex> Enum.to_list(1..3)
[1, 2, 3]

first..last//stepSource

Создаёт диапазон от first до last с step.

См. модуль Range для получения дополнительной информации.

Примеры

iex> 0 in 1..3//1
false
iex> 2 in 1..3//1
true
iex> 2 in 1..3//2
false

iex> Enum.to_list(1..3//1)
[1, 2, 3]
iex> Enum.to_list(1..3//2)
[1, 3]
iex> Enum.to_list(3..1//-1)
[3, 2, 1]
iex> Enum.to_list(1..0//1)
[]

!valueSource

Логический оператор "не".

Принимает любое значение (не только булевы значения) и возвращает true , если value равно false или nil; в противном случае возвращает false.

Запрещено в условиях защиты.

Примеры

iex> !Enum.empty?([])
false

iex> !List.first([])
true

left <> rightSource

Оператор бинарной конкатенации. Объединяет две бинарные строки.

Генерирует исключение ArgumentError, если один из операндов не является бинарной строкой.

Примеры

iex> "foo" <> "bar"
"foobar"

Оператор <>/2 также может использоваться в шаблонах (и условиях защиты), если левый операнд — это литеральная бинарная строка:

iex> "foo" <> x = "foobar"
iex> x
"bar"

x <> "bar" = "foobar" приведет к исключению ArgumentError.

left =~ rightSource

@spec String.t() =~ (String.t() | Regex.t()) :: boolean()

Оператор сопоставления по тексту. Сопоставляет терм в left с регулярным выражением или строкой в right.

Если right — регулярное выражение, возвращает true если left соответствует right.

Если right — строка, возвращает true если left содержит right.

Примеры

iex> "abcd" =~ ~r/c(d)/
true

iex> "abcd" =~ ~r/e/
false

iex> "abcd" =~ ~r//
true

iex> "abcd" =~ "bc"
true

iex> "abcd" =~ "ad"
false

iex> "abcd" =~ "abcd"
true

iex> "abcd" =~ ""
true

Для получения дополнительной информации о регулярных выражениях, пожалуйста, обратитесь к модулю Regex.

@exprSource

Унарный оператор атрибута модуля.

Читает и записывает атрибуты в текущем модуле.

Канонический пример атрибутов — это аннотация, что модуль реализует поведение OTP, такое как GenServer:

defmodule MyServer do
  @behaviour GenServer
  # ... callbacks ...
end

По умолчанию Elixir поддерживает все атрибуты модулей, поддерживаемые Erlang, но также могут использоваться и пользовательские атрибуты:

defmodule MyServer do
  @my_data 13
  IO.inspect(@my_data)
  #=> 13
end

В отличие от Erlang, такие атрибуты по умолчанию не хранятся в модуле, так как в Elixir часто используются пользовательские атрибуты для хранения временных данных, доступных на этапе компиляции. Пользовательские атрибуты можно настроить, чтобы они вели себя как в Erlang, используя Module.register_attribute/3.

Важно: Библиотеки и фреймворки должны учитывать префикс нижнего подчёркивания для любых атрибутов модулей, которые являются приватными, например, @_my_data, чтобы инструменты автодополнения не показывали их в подсказках и предложениях.

И наконец, обратите внимание, что атрибуты также можно читать внутри функций:

defmodule MyServer do
  @my_data 11
  def first_data, do: @my_data
  @my_data 13
  def second_data, do: @my_data
end

MyServer.first_data()
#=> 11

MyServer.second_data()
#=> 13

Важно отметить, что чтение атрибута создаёт снимок его текущего значения. Иными словами, значение считывается на этапе компиляции, а не во время выполнения. См. модуль Module для других функций управления атрибутами модулей.

Внимание! Несколько ссылок на один и тот же атрибут

Как упоминалось выше, каждый раз при чтении атрибута модуля создаётся снимок его текущего значения. Поэтому, если вы храните большие значения в атрибутах модулей (например, встраиваете внешние файлы в атрибуты модулей), следует избегать множественных ссылок на один и тот же атрибут. Например, не делайте так:

@files %{
  example1: File.read!("lib/example1.data"),
  example2: File.read!("lib/example2.data")
}

def example1, do: @files[:example1]
def example2, do: @files[:example2]

В приведенном выше примере каждая ссылка на @files может привести к полной и отдельной копии всего атрибута модуля @files. Вместо этого обратитесь к атрибуту модуля один раз в приватной функции:

@files %{
  example1: File.read!("lib/example1.data"),
  example2: File.read!("lib/example2.data")
}

defp files(), do: @files
def example1, do: files()[:example1]
def example2, do: files()[:example2]

Внимание! Зависимости от этапа компиляции

Помните, что ссылки на другие модули, даже в атрибутах модулей, создают зависимости от этапа компиляции к этим модулям.

Например, рассмотрите этот распространённый шаблон:

@values [:foo, :bar, :baz]

def handle_arg(arg) when arg in @values do
  ...
end

Хотя приведенный выше пример верен, представьте, что вместо этого у вас есть фактические имена модулей в атрибуте модуля, как в этом случае:

@values [Foo, Bar, Baz]

def handle_arg(arg) when arg in @values do
  ...
end

Код выше определит зависимость от этапа компиляции от модулей Foo, Bar, и Baz, таким образом, что при изменении любого из них текущему модулю придётся перекомпилироваться. В таких случаях может быть предпочтительнее вообще избегать атрибута модуля:

def handle_arg(arg) when arg in [Foo, Bar, Baz] do
  ...
end
END_OF_DOCUMENT_MARKER

alias!(alias)Source

При использовании внутри цитирования помечает, что данный псевдоним не должен подвергаться гигиене. Это означает, что псевдоним будет расширен при расширении макроса.

См. Kernel.SpecialForms.quote/2 для получения дополнительной информации.

END_OF_DOCUMENT_MARKER

apply(fun, args)Source

@spec apply((... -> any()), [any()]) :: any()

Вызывает заданную анонимную функцию fun со списком аргументов args.

Если количество аргументов известно на этапе компиляции, предпочтительнее использовать fun.(arg_1, arg_2, ..., arg_n) — оно более понятно, чем apply(fun, [arg_1, arg_2, ..., arg_n]).

Встраивается компилятором.

Примеры

iex> apply(fn x -> x * 2 end, [2])
4

apply(module, function_name, args)Source

@spec apply(module(), function_name :: atom(), [any()]) :: any()

Вызывает заданную функцию из module со списком аргументов args.

apply/3 используется для вызова функций, где модуль, имя функции или аргументы определяются динамически во время выполнения. По этой причине вы не можете вызывать макросы с помощью apply/3, только функции.

Если количество аргументов и имя функции известны на этапе компиляции, предпочтительнее использовать module.function(arg_1, arg_2, ..., arg_n) — оно более понятно, чем apply(module, :function, [arg_1, arg_2, ..., arg_n]).

apply/3 не может использоваться для вызова закрытых функций.

Встраивается компилятором.

Примеры

iex> apply(Enum, :reverse, [[1, 2, 3]])
[3, 2, 1]

binary_slice(binary, range)Source

Возвращает двоичную строку от смещения, заданного началом диапазона, до смещения, заданного концом диапазона.

Если начало или конец диапазона отрицательны, они преобразуются в положительные индексы на основе размера двоичной строки. Например, -1 означает последний байт двоичной строки.

Аналогично binary_part/3, но работает с диапазонами и не разрешено в охранных выражениях.

Функция работает с байтами. Для операции среза, учитывающей символы, см. String.slice/2.

Примеры

iex> binary_slice("elixir", 0..5)
"elixir"
iex> binary_slice("elixir", 1..3)
"lix"
iex> binary_slice("elixir", 1..10)
"lixir"

iex> binary_slice("elixir", -4..-1)
"ixir"
iex> binary_slice("elixir", -4..6)
"ixir"
iex> binary_slice("elixir", -10..10)
"elixir"

Для диапазонов, где start > stop, необходимо явно указать их как возрастающие:

iex> binary_slice("elixir", 2..-1//1)
"ixir"
iex> binary_slice("elixir", 1..-2//1)
"lixi"

Можно использовать ../0 как сокращение для 0..-1//1, которое возвращает всю двоичную строку как есть:

iex> binary_slice("elixir", ..)
"elixir"

Шаг может быть любым положительным числом. Например, чтобы получить каждый второй символ двоичной строки:

iex> binary_slice("elixir", 0..-1//2)
"eii"

Если первая позиция находится за пределами строки или после последней позиции диапазона, возвращается пустая строка:

iex> binary_slice("elixir", 10..3//1)
""
iex> binary_slice("elixir", -10..-7)
""
iex> binary_slice("a", 1..1500)
""

binary_slice(binary, start, size)Source

Возвращает двоичную строку, начинающуюся со смещения start и заданного size.

Аналогично binary_part/3, но если start + size больше размера двоичной строки, она автоматически обрезается до размера двоичной строки вместо повышения ошибки. В отличие от binary_part/3, эта функция не разрешена в охранных выражениях.

Функция работает с байтами. Для операции среза, учитывающей символы, см. String.slice/3.

Примеры

iex> binary_slice("elixir", 0, 6)
"elixir"
iex> binary_slice("elixir", 0, 5)
"elixi"
iex> binary_slice("elixir", 1, 4)
"lixi"
iex> binary_slice("elixir", 0, 10)
"elixir"

Если start отрицательное, оно нормализуется относительно размера двоичной строки и ограничено значением 0:

iex> binary_slice("elixir", -3, 10)
"xir"
iex> binary_slice("elixir", -10, 10)
"elixir"

Если size равно нулю, возвращается пустая двоичная строка:

iex> binary_slice("elixir", 1, 0)
""

Если start больше или равно размеру двоичной строки, возвращается пустая двоичная строка:

iex> binary_slice("elixir", 10, 10)
""

binding(context \\ nil)Source

Возвращает контекст связывания для данного контекста в виде списка ключевых слов.

В возвращенном результате ключи — имена переменных, а значения — соответствующие значения переменных.

Если указанный context равен nil (по умолчанию), возвращается контекст связывания для текущего контекста.

Примеры

iex> x = 1
iex> binding()
[x: 1]
iex> x = 2
iex> binding()
[x: 2]

iex> binding(:foo)
[]
iex> var!(x, :foo) = 1
1
iex> binding(:foo)
[x: 1]

dbg(code \\ quote do binding() end, options \\ [])Source

Отлаживает заданный code.

dbg/2 может использоваться для отладки данного code через настраиваемую функцию отладки. Возвращает результат заданного кода.

Примеры

Рассмотрим этот вызов dbg/2:

dbg(Atom.to_string(:debugging))
#=> "debugging"

Возвращает строку "debugging", которая является результатом вызова Atom.to_string/1. Кроме того, приведенный выше вызов выводит:

[my_file.ex:10: MyMod.my_fun/0]
Atom.to_string(:debugging) #=> "debugging"

По умолчанию, функция отладки выводит дополнительную отладочную информацию при работе с конвейерами. Она выводит значения на каждой "ступеньке" конвейера.

"Elixir is cool!"
|> String.trim_trailing("!")
|> String.split()
|> List.first()
|> dbg()
#=> "Elixir"

Приведенный выше код выводит:

[my_file.ex:10: MyMod.my_fun/0]
"Elixir is cool!" #=> "Elixir is cool!"
|> String.trim_trailing("!") #=> "Elixir is cool"
|> String.split() #=> ["Elixir", "is", "cool"]
|> List.first() #=> "Elixir"

Без аргументов, dbg() отлаживает информацию о текущем контексте связывания. См. binding/1.

Настройка функции отладки

Одним из преимуществ dbg/2 является возможность конфигурации логики отладки, что позволяет инструментам расширять dbg с улучшенным поведением. Это делается, например, IEx, которая расширяет dbg интерактивной оболочкой, где вы можете напрямую просматривать и получать доступ к значениям.

Функция отладки может быть настроена во время компиляции через ключ :dbg_callback приложения :elixir. Функция отладки должна быть кортежем {module, function, args}. Функция function в module будет вызвана с тремя аргументами, предваряющими args.

  1. AST выражения code
  2. AST выражения options
  3. Среда Macro.Env вызова dbg/2

Функция отладки вызывается во время компиляции и также должна возвращать AST. AST ожидается, что, в конечном итоге, вернет результат оценки отлаживаемого выражения.

Вот простой пример:

defmodule MyMod do
  def debug_fun(code, options, caller, device) do
    quote do
      result = unquote(code)
      IO.inspect(unquote(device), result, label: unquote(Macro.to_string(code)))
    end
  end
end

Для настройки функции отладки:

# In config/config.exs
config :elixir, :dbg_callback, {MyMod, :debug_fun, [:stdio]}

Функция отладки по умолчанию

По умолчанию, функция отладки — Macro.dbg/3. Она просто выводит информацию о коде в стандартный вывод и возвращает значение, возвращаемое при оценке code. options используются для управления тем, как просматриваются термины. Они совпадают с параметрами, принимаемыми функцией inspect/2.

def(call, expr \\ nil)Source

Определяет общедоступную функцию с заданным именем и телом.

Примеры

defmodule Foo do
  def bar, do: :baz
end

Foo.bar()
#=> :baz

Функция, которая ожидает аргументов, может быть определена следующим образом:

defmodule Foo do
  def sum(a, b) do
    a + b
  end
end

В приведенном выше примере определена функция sum/2; эта функция принимает два аргумента и возвращает их сумму.

Аргументы по умолчанию

\\ используется для задания значения по умолчанию для параметра функции. Например:

defmodule MyMath do
  def multiply_by(number, factor \\ 2) do
    number * factor
  end
end

MyMath.multiply_by(4, 3)
#=> 12

MyMath.multiply_by(4)
#=> 8

Компилятор переводит это в несколько функций с разными арностью, здесь MyMath.multiply_by/1 и MyMath.multiply_by/2, которые представляют случаи, когда аргументы для параметров с значениями по умолчанию передаются или не передаются.

При определении функции с аргументами по умолчанию и несколькими явно объявленными разделами, необходимо написать заголовок функции, который объявляет значения по умолчанию. Например:

defmodule MyString do
  def join(string1, string2 \\ nil, separator \\ " ")

  def join(string1, nil, _separator) do
    string1
  end

  def join(string1, string2, separator) do
    string1 <> separator <> string2
  end
end

Обратите внимание, что \\ нельзя использовать с анонимными функциями, поскольку у них может быть только одна арность.

Списки ключевых слов с аргументами по умолчанию

Функции, содержащие множество аргументов, могут извлечь выгоду из использования списков ключевых слов для группировки и передачи атрибутов как одного значения.

defmodule MyConfiguration do
  @default_opts [storage: "local"]

  def configure(resource, opts \\ []) do
    opts = Keyword.merge(@default_opts, opts)
    storage = opts[:storage]
    # ...
  end
end

Разница между использованием Map и Keyword для хранения многих аргументов заключается в ключах Keyword:

  • должны быть атомами
  • могут быть заданы несколько раз
  • упорядочены, как указано разработчиком

Имена функций и переменных

Имена функций и переменных имеют следующий синтаксис: нижняя регистровая ASCII буква или подчеркивание, за которыми следуют любое количество нижняя или верхняя регистровые ASCII буквы, цифры или подчеркивания. Дополнительно они могут заканчиваться либо знаком восклицания, либо знаком вопроса.

Для переменных любой идентификатор, начинающийся с подчеркивания, должен указывать на неиспользуемую переменную. Например:

def foo(bar) do
  []
end
#=> warning: variable bar is unused

def foo(_bar) do
  []
end
#=> no warning

def foo(_bar) do
  _bar
end
#=> warning: the underscored variable "_bar" is used after being set

rescue/catch/after/else

Тела функций поддерживают rescue, catch, after, и else как и Kernel.SpecialForms.try/1 (известно как "явное try"). Например, следующие две функции эквивалентны:

def convert(number) do
  try do
    String.to_integer(number)
  rescue
    e in ArgumentError -> {:error, e.message}
  end
end

def convert(number) do
  String.to_integer(number)
rescue
  e in ArgumentError -> {:error, e.message}
end
END_OF_DOCUMENT_MARKER

defdelegate(funs, opts)Source

Определяет функцию, которая делегирует вызов другой модуль.

Функции, определенные с помощью defdelegate/2, являются публичными и могут вызываться извне модуля, в котором они определены, как если бы они были определены с помощью def/2. Следовательно, defdelegate/2 относится к расширению публичного API текущего модуля. Если требуется вызвать функцию, определенную в другом модуле, без указания полного имени модуля, используйте alias/2 для сокращения имени модуля или import/2, чтобы вообще опустить имя модуля при вызове.

Делегирование работает только с функциями; делегирование макросов не поддерживается.

См. def/2 для правил именования и аргументов по умолчанию.

Параметры

  • :to - модуль, которому будет делегирован вызов.

  • :as - функция, которая будет вызвана в целевом модуле, указанном в :to. Этот параметр необязателен и по умолчанию равен имени делегируемой функции (funs).

Примеры

defmodule MyList do
  defdelegate reverse(list), to: Enum
  defdelegate other_reverse(list), to: Enum, as: :reverse
end

MyList.reverse([1, 2, 3])
#=> [3, 2, 1]

MyList.other_reverse([1, 2, 3])
#=> [3, 2, 1]

defexception(fields)Source

Определяет исключение.

Исключения представляют собой структуры, поддерживаемые модулем, реализующим поведение Exception. Поведение Exception требует реализации двух функций:

  • exception/1 - принимает аргументы, переданные в raise/2, и возвращает структуру исключения. Реализация по умолчанию принимает либо набор ключевых аргументов, которые объединяются в структуру, либо строку, которая используется в качестве сообщения об исключении.

  • message/1 - принимает структуру исключения и должна вернуть её сообщение. Чаще всего у исключений есть поле message, которое по умолчанию используется этой функцией. Однако, если исключение не имеет поля message, эта функция должна быть явно реализована.

Поскольку исключения являются структурами, API, поддерживаемый defstruct/1, также доступен в defexception/1.

Выбрасывание исключений

Наиболее распространенный способ выброса исключения - через raise/2:

defmodule MyAppError do
  defexception [:message]
end

value = [:hello]

raise MyAppError,
  message: "did not get what was expected, got: #{inspect(value)}"

Во многих случаях удобнее передать ожидаемое значение в raise/2 и сгенерировать сообщение в обработчике Exception.exception/1:

defmodule MyAppError do
  defexception [:message]

  @impl true
  def exception(value) do
    msg = "did not get what was expected, got: #{inspect(value)}"
    %MyAppError{message: msg}
  end
end

raise MyAppError, value

Приведенный выше пример демонстрирует предпочтительную стратегию настройки сообщений об исключениях.

defguard(guard)Source

@spec defguard(Macro.t()) :: Macro.t()

Генерирует макрос, подходящий для использования в выражениях-стражах.

Вызывает ошибку во время компиляции, если определение использует выражения, запрещенные в стражах, и в противном случае создает макрос, который можно использовать как внутри, так и вне стражей.

В Elixir принято именовать функции/макросы, разрешенные в стражах, префиксом is_, например is_list/1. Однако, если функция/макрос возвращает булево значение и не разрешен в стражах, он не должен иметь префикс и оканчиваться вопросительным знаком, например Keyword.keyword?/1.

Пример

defmodule Integer.Guards do
  defguard is_even(value) when is_integer(value) and rem(value, 2) == 0
end

defmodule Collatz do
  @moduledoc "Tools for working with the Collatz sequence."
  import Integer.Guards

  @doc "Determines the number of steps `n` takes to reach `1`."
  # If this function never converges, please let me know what `n` you used.
  def converge(n) when n > 0, do: step(n, 0)

  defp step(1, step_count) do
    step_count
  end

  defp step(n, step_count) when is_even(n) do
    step(div(n, 2), step_count + 1)
  end

  defp step(n, step_count) do
    step(3 * n + 1, step_count + 1)
  end
end

defguardp(guard)Source

@spec defguardp(Macro.t()) :: Macro.t()

Генерирует частный макрос, подходящий для использования в выражениях-стражах.

Вызывает ошибку во время компиляции, если определение использует выражения, запрещенные в стражах, и в противном случае создает частный макрос, который может быть использован как внутри, так и вне стражей в текущем модуле.

Аналогично defmacrop/2, defguardp/1 должен быть определен до его использования в текущем модуле.

defimpl(name, opts, do_block \\ [])Source

Определяет реализацию для данного протокола.

См. модуль Protocol для получения дополнительной информации.

defmacro(call, expr \\ nil)Source

Определяет публичный макрос с заданным именем и телом.

Макросы должны быть определены до их использования.

См. def/2 для правил именования и аргументов по умолчанию.

Примеры

defmodule MyLogic do
  defmacro unless(expr, opts) do
    quote do
      if !unquote(expr), unquote(opts)
    end
  end
end

require MyLogic

MyLogic.unless false do
  IO.puts("It works")
end

defmacrop(call, expr \\ nil)Source

Определяет закрытый макрос с заданным именем и телом.

Закрытые макросы доступны только из того же модуля, в котором они определены.

Закрытые макросы должны быть определены до их использования.

См. defmacro/2 для получения дополнительной информации, и см. def/2 для правил именования и аргументов по умолчанию.

defmodule(alias, do_block)Source

Определяет модуль с заданным именем и содержимым.

Этот макрос определяет модуль с заданным alias в качестве имени и заданным содержимым. Он возвращает кортеж из четырёх элементов:

  • :module
  • имя модуля
  • бинарное содержимое модуля
  • результат выполнения блока содержимого

Примеры

defmodule Number do
  def one, do: 1
  def two, do: 2
end
#=> {:module, Number, <<70, 79, 82, ...>>, {:two, 0}}

Number.one()
#=> 1

Number.two()
#=> 2

Вложенность

Вложенность модуля внутри другого модуля влияет на имя вложенного модуля:

defmodule Foo do
  defmodule Bar do
  end
end

В примере выше создаются два модуля — Foo и Foo.Bar. При вложенности Elixir автоматически создаёт псевдоним для внутреннего модуля, позволяя обращаться ко второму модулю Foo.Bar как к Bar в том же лексическом пространстве, где он определён (в модуле Foo). Это происходит только если вложенный модуль определён через псевдоним.

Если модуль Foo.Bar перемещен в другое место, ссылки на Bar в модуле Foo необходимо обновить на полное имя (Foo.Bar) или установить псевдоним в модуле Foo с помощью Kernel.SpecialForms.alias/2.

defmodule Foo.Bar do
  # code
end

defmodule Foo do
  alias Foo.Bar
  # code here can refer to "Foo.Bar" as just "Bar"
end

Динамические имена

Имена модулей в Elixir могут быть динамически сгенерированы. Это очень полезно при работе с макросами. Например, можно написать:

defmodule String.to_atom("Foo#{1}") do
  # contents ...
end

Elixir примет любое имя модуля, если выражение, переданное в качестве первого аргумента в defmodule/2, вычисляется до атома. Обратите внимание, что при использовании динамического имени Elixir не будет вкладывать имя в текущий модуль и не будет автоматически устанавливать псевдоним.

Зарезервированные имена модулей

Если вы попытаетесь определить модуль, который уже существует, вы получите предупреждение о том, что модуль был переопределен.

Существуют некоторые модули, которые Elixir пока не реализует, но может реализовать в будущем. Эти модули зарезервированы, и их определение приведёт к ошибке компиляции:

defmodule Any do
  # code
end
** (CompileError) iex:1: module Any is reserved and cannot be defined

Elixir зарезервировал следующие имена модулей: Elixir, Any, BitString, PID, и Reference.

defoverridable(keywords_or_behaviour)Source

Делает заданные определения в текущем модуле переопределяемыми.

Если пользователь определит новую функцию или макрос с тем же именем и арностью, то переопределяемые определения будут отброшены. В противном случае будут использованы исходные определения.

Возможна ситуация, когда переопределённое определение имеет другую видимость, чем оригинальное: публичная функция может быть переопределена приватной функцией и наоборот.

Макросы не могут быть переопределены как функции, и наоборот.

Пример

defmodule DefaultMod do
  defmacro __using__(_opts) do
    quote do
      def test(x, y) do
        x + y
      end

      defoverridable test: 2
    end
  end
end

defmodule ChildMod do
  use DefaultMod

  def test(x, y) do
    x * y + super(x, y)
  end
end

Как видно из примера выше, super можно использовать для вызова реализации по умолчанию.

Примечание: используйте defoverridable с осторожностью. Если вам нужно определить несколько модулей с одинаковым поведением, лучше перенести реализацию по умолчанию в вызывающий модуль и проверить наличие обратного вызова с помощью Code.ensure_loaded?/1 и function_exported?/3.

Например, в примере выше, представьте, что есть модуль, который вызывает функцию test/2. Этот модуль может быть определён следующим образом:

defmodule CallsTest do
  def receives_module_and_calls_test(module, x, y) do
    if Code.ensure_loaded?(module) and function_exported?(module, :test, 2) do
      module.test(x, y)
    else
      x + y
    end
  end
end

Пример с поведением

Вы также можете передать поведение в defoverridable, и оно отметит все обратные вызовы в поведении как переопределяемые:

defmodule Behaviour do
  @callback test(number(), number()) :: number()
end

defmodule DefaultMod do
  defmacro __using__(_opts) do
    quote do
      @behaviour Behaviour

      def test(x, y) do
        x + y
      end

      defoverridable Behaviour
    end
  end
end

defmodule ChildMod do
  use DefaultMod

  def test(x, y) do
    x * y + super(x, y)
  end
end

defp(call, expr \\ nil)Source

Определяет приватную функцию с заданным именем и телом.

Приватные функции доступны только внутри модуля, в котором они определены. Попытка доступа к приватной функции извне модуля, в котором она определена, приводит к исключению UndefinedFunctionError.

См. def/2 для получения дополнительной информации.

Примеры

defmodule Foo do
  def bar do
    sum(1, 2)
  end

  defp sum(a, b), do: a + b
end

Foo.bar()
#=> 3

Foo.sum(1, 2)
** (UndefinedFunctionError) undefined function Foo.sum/2

defprotocol(name, do_block)Source

Определяет протокол.

См. модуль Protocol для получения дополнительной информации.

defstruct(fields)Source

Определяет структуру.

Структура — это помеченная карта, которая позволяет разработчикам предоставлять значения по умолчанию для ключей, метки для использования в полиморфных диспетчерах и проверки типов на этапе компиляции. Для получения дополнительной информации о структурах, обратитесь к Kernel.SpecialForms.%/2.

Определение структуры возможно только в рамках одного модуля, поскольку структура привязана к самому модулю. Вызов defstruct/1 также определяет функцию __struct__/0, которая возвращает саму структуру.

Примеры

defmodule User do
  defstruct name: nil, age: nil
end

Поля структуры оцениваются на этапе компиляции, что позволяет им быть динамическими. В примере ниже, 10 + 11 оценивается на этапе компиляции, и поле age хранится со значением 21:

defmodule User do
  defstruct name: nil, age: 10 + 11
end

Аргумент fields обычно представляет собой список ключевых слов, где ключи — атомы имён полей, а значения — соответствующие значения по умолчанию. defstruct/1 также поддерживает список атомов в качестве аргумента: в этом случае атомы в списке будут использоваться в качестве имён полей структуры, и все они будут иметь значение по умолчанию nil.

defmodule Post do
  defstruct [:title, :content, :author]
end

Наследование

Несмотря на то, что структуры являются картами, по умолчанию структуры не реализуют ни один из протоколов, реализованных для карт. Например, попытка использовать протокол со структурой User приводит к ошибке:

john = %User{name: "John"}
MyProtocol.call(john)
** (Protocol.UndefinedError) protocol MyProtocol not implemented for %User{...}

defstruct/1, однако, позволяет реализовывать протоколы по умолчанию. Это можно сделать, определив атрибут @derive как список перед вызовом defstruct/1:

defmodule User do
  @derive MyProtocol
  defstruct name: nil, age: nil
end

MyProtocol.call(john) # it works!

Частый пример — наследовать протокол Inspect для скрытия определённых полей при печати структуры:

defmodule User do
  @derive {Inspect, only: :name}
  defstruct name: nil, age: nil
end

Для каждого протокола в @derive, Elixir проверит, реализован ли протокол для Any. Если реализация Any определяет обратный вызов __deriving__/3, этот обратный вызов будет вызван, и он должен определить реализующий модуль. В противном случае реализация, просто указывающая на реализацию Any, автоматически наследуется. Более подробную информацию об обратном вызове __deriving__/3 см. в Protocol.derive/3.

Принудительное использование ключей

При создании структуры Elixir автоматически гарантирует, что все ключи принадлежат структуре:

%User{name: "john", unknown: :key}
** (KeyError) key :unknown not found in: %User{age: 21, name: nil}

Elixir также позволяет разработчикам принудительно требовать, чтобы при создании структуры всегда указывались определённые ключи:

defmodule User do
  @enforce_keys [:name]
  defstruct name: nil, age: 10 + 11
end

Теперь попытка создать структуру без ключа name завершится ошибкой:

%User{age: 21}
** (ArgumentError) the following keys must also be given when building struct User: [:name]

Обратите внимание, что @enforce_keys — это просто гарантия на этапе компиляции, которая помогает разработчикам при создании структур. Она не применяется к обновлениям и не обеспечивает никакой валидации значений.

Типы

Рекомендуется определять типы для структур. По соглашению такой тип называется t. Для определения структуры внутри типа используется синтаксис литералов структур:

defmodule User do
  defstruct name: "John", age: 25
  @type t :: %__MODULE__{name: String.t(), age: non_neg_integer}
end

Рекомендуется использовать синтаксис структуры только при определении типа структуры. При ссылке на другую структуру лучше использовать User.t() вместо %User{}.

Типы полей структуры, которые не включены в %User{}, по умолчанию принимают тип term() (см. term/0).

Структуры, внутренняя структура которых является приватной для локального модуля (паттерн-сопоставление с ними или прямой доступ к их полям не должен быть разрешён), должны использовать атрибут @opaque. Структуры, внутренняя структура которых является публичной, должны использовать @type.

destructure(left, right)Source

Деструктурирует два списка, присваивая каждый элемент в правом списке соответствующему элементу в левом.

В отличие от паттерн-сопоставления с помощью =, если размеры левого и правого списков не совпадают, деструктурирование просто останавливается, а не генерирует ошибку.

Примеры

iex> destructure([x, y, z], [1, 2, 3, 4, 5])
iex> {x, y, z}
{1, 2, 3}

В примере выше, даже если правый список содержит больше элементов, чем левый, деструктурирование работает нормально. Если правый список меньше, оставшиеся элементы просто устанавливаются в nil:

iex> destructure([x, y, z], [1])
iex> {x, y, z}
{1, nil, nil}

Левая часть поддерживает любые выражения, которые можно использовать в левой части сопоставления:

x = 1
destructure([^x, y, z], [1, 2, 3])

Пример выше будет работать только если x соответствует первому значению в правом списке. В противном случае будет сгенерировано исключение MatchError (как и оператор =).

END_OF_DOCUMENT_MARKER

exit(reason)Source

@spec exit(term()) :: no_return()

Останавливает выполнение вызывающего процесса с заданным основанием.

Поскольку оценка этой функции приводит к завершению процесса, она не имеет возвращаемого значения.

Встраивается компилятором.

Примеры

Когда процесс завершается, по умолчанию он завершается с основанием :normal. Также можно явно вызвать exit/1, если нужно завершить процесс, но не сигнализировать об ошибке:

exit(:normal)

В случае возникновения ошибки можно также использовать exit/1 с другим основанием:

exit(:seems_bad)

Если причина выхода не :normal, все процессы, связанные с завершившимся процессом, потерпят крах (если они не обрабатывают выходы).

Выходы OTP

Выходы используются OTP для определения того, завершился ли процесс аномально или нет. Следующие выходы считаются «нормальными»:

  • exit(:normal)
  • exit(:shutdown)
  • exit({:shutdown, term})

Завершение с любой другой причиной считается аномальным и обрабатывается как сбой. Это означает, что включается стандартное поведение надзирателя, генерируются сообщения об ошибках и т.д.

Это поведение используется во многих местах. Например, ExUnit использует exit(:shutdown) при завершении процесса тестирования, чтобы сообщить связанным процессам, деревьям надзора и т.д. о вежливом завершении работы.

Выходы командной строки

На основании сигналов завершения, упомянутых выше, если процесс, запущенный из командной строки, завершается с любой из трёх причин выше, его выход считается нормальным, и процесс операционной системы завершается со статусом 0.

Однако, можно настроить сигнал завершения операционной системы, вызвав:

exit({:shutdown, integer})

Это заставит процесс операционной системы завершиться со статусом, заданным integer, одновременно сигнализируя всем связанным процессам Erlang о вежливом завершении работы.

Любая другая причина выхода приведёт к завершению процесса операционной системы со статусом 1 и краху связанных процессов Erlang.

END_OF_DOCUMENT_MARKER ```

function_exported?(module, function, arity)Source

@spec function_exported?(module(), atom(), arity()) :: boolean()

Возвращает true, если модуль загружен и содержит общедоступную функцию с заданным именем и арностью, в противном случае false.

Обратите внимание, что эта функция не загружает модуль в случае его отсутствия. Для получения дополнительной информации см. Code.ensure_loaded/1.

Встраивается компилятором.

Примеры

iex> function_exported?(Enum, :map, 2)
true

iex> function_exported?(Enum, :map, 10)
false

iex> function_exported?(List, :to_string, 1)
true

get_and_update_in(path, fun)Source

Получает значение и обновляет вложенную структуру данных с помощью заданной функции.

Аналогично get_and_update_in/3, за исключением того, что путь извлекается с помощью макроса, а не передаётся в виде списка. Например:

get_and_update_in(opts[:foo][:bar], &{&1, &1 + 1})

Эквивалентно:

get_and_update_in(opts, [:foo, :bar], &{&1, &1 + 1})

Это также работает со вложенными структурами и способом указания путей с помощью макроса:

get_and_update_in(struct.foo.bar, &{&1, &1 + 1})

Обратите внимание, что для работы этого макроса весь путь должен быть виден этому макросу. См. раздел «Пути» ниже.

Примеры

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_and_update_in(users["john"].age, &{&1, &1 + 1})
{27, %{"john" => %{age: 28}, "meg" => %{age: 23}}}

Пути

Путь может начинаться с переменной, локального или удалённого вызова и должен быть продолжен одним или несколькими:

  • &{var} - обращается к ключу в переменной; в случае, если переменная имеет значение nil, возвращается nil

  • &{key} - обращается к полю карты/структуры; в случае отсутствия поля генерируется ошибка

Вот некоторые допустимые пути:

users["john"][:age]
users["john"].age
User.all()["john"].age
all_users()["john"].age

Вот некоторые недопустимые:

# Does a remote call after the initial value
users["john"].do_something(arg1, arg2)

# Does not access any key or field
users

get_and_update_in(data, keys, fun)Source

@spec get_and_update_in(
  structure,
  keys,
  (term() | nil -> {current_value, new_value} | :pop)
) :: {current_value, new_structure :: structure}
when structure: Access.t(),
     keys: [any(), ...],
     current_value: Access.value(),
     new_value: Access.value()

Получает значение и обновляет вложенную структуру.

data — это вложенная структура (то есть карта, список ключевых слов или структура, реализующая поведение Access).

Аргумент fun получает значение (или nil, если значение отсутствует) и должен вернуть одно из следующих значений:

  • двухэлементная кортеж {old_value, new_value}. В этом случае old_value — это полученное значение, которое можно, возможно, обработать перед возвратом. new_value — новое значение, которое должно быть сохранено под указанным ключом.

  • nil, что подразумевает удаление текущего значения из структуры и возврат этого значения.

Эта функция использует модуль Access для обхода структур в соответствии с заданными ключами, если fun не является функцией, что подробно описано в последующем разделе.

Примеры

Эта функция полезна, когда необходимо получить текущее значение (или значение, вычисленное в зависимости от текущего значения) и обновить его одновременно. Например, её можно использовать для чтения текущего возраста пользователя и увеличения его на единицу за один проход:

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_and_update_in(users, ["john", :age], &{&1, &1 + 1})
{27, %{"john" => %{age: 28}, "meg" => %{age: 23}}}

Обратите внимание, что текущее значение, переданное анонимной функции, может быть nil. Если любое из промежуточных значений равно nil, произойдёт исключение:

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_and_update_in(users, ["jane", :age], &{&1, &1 + 1})
** (ArgumentError) could not put/update key :age on a nil value

Функции в качестве ключей

Если ключ является функцией, функция будет вызвана с тремя аргументами:

  • операция (get_and_update_in/3)
  • данные для доступа
  • функция, которая будет вызвана далее

Это означает, что get_and_update_in/3 можно расширить для предоставления настраиваемых поисков. Недостатком является то, что функции не могут храниться в качестве ключей в структурах данных для доступа.

Когда один из ключей является функцией, функция вызывается. В примере ниже мы используем функцию для получения и увеличения всех возрастов в списке:

iex> users = [%{name: "john", age: 27}, %{name: "meg", age: 23}]
iex> all = fn :get_and_update, data, next ->
...>   data |> Enum.map(next) |> Enum.unzip()
...> end
iex> get_and_update_in(users, [all, :age], &{&1, &1 + 1})
{[27, 23], [%{name: "john", age: 28}, %{name: "meg", age: 24}]}

Если предыдущее значение перед вызовом функции — nil, функция получит nil в качестве значения и должна обработать его соответствующим образом (будь то ошибочная обработка или предоставление разумного значения по умолчанию).

Модуль Access поставляется с множеством удобных функций доступа, таких как анонимная функция fn x -> {x, x + 1} end выше. См. Access.all/0, Access.key/2 и другие примеры.

get_in(data, keys)Source

@spec get_in(Access.t(), [term(), ...]) :: term()

Получает значение из вложенной структуры.

Использует модуль Access для обхода структур в соответствии с заданными ключами, если fun не является функцией, что подробно описано в последующем разделе.

Обратите внимание, что если ни один из заданных ключей не является функцией, редко есть причина использовать get_in вместо написания «обычного» кода Elixir с использованием сопоставления с образцом.

Примеры

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_in(users, ["john", :age])
27
iex> # Equivalent to:
iex> users["john"][:age]
27

get_in/2 также может использовать аксессоры в модуле Access для обхода более сложных структур данных. Например, здесь мы используем Access.all/0 для обхода списка:

iex> users = [%{name: "john", age: 27}, %{name: "meg", age: 23}]
iex> get_in(users, [Access.all(), :age])
[27, 23]

В случае если любой из компонентов возвращает nil, будет возвращено nil, и get_in/2 не будет продолжать обход:

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> get_in(users, ["unknown", :age])
nil
iex> # Equivalent to:
iex> users["unknown"][:age]
nil

iex> users = nil
iex> get_in(users, [Access.all(), :age])
nil

В качестве альтернативы, если вам нужно получить доступ к сложным структурам данных, вы можете использовать сопоставление с образцом:

case users do
  %{"john" => %{age: age}} -> age
  _ -> default_value
end

Функции в качестве ключей

Если ключ, переданный get_in/2, является функцией, функция будет вызвана с тремя аргументами:

  • операция (get_in/2)
  • данные для доступа
  • функция, которая будет вызвана далее

Это означает, что get_in/2 можно расширить для предоставления настраиваемых поисков. Именно так работает ключ Access.all/0 в предыдущем разделе. Например, мы можем вручную реализовать такой обход следующим образом:

iex> users = [%{name: "john", age: 27}, %{name: "meg", age: 23}]
iex> all = fn :get, data, next -> Enum.map(data, next) end
iex> get_in(users, [all, :age])
[27, 23]

Модуль Access поставляется с множеством удобных функций доступа. См. Access.all/0, Access.key/2 и другие примеры.

Работа со структурами

По умолчанию структуры не реализуют поведение Access, необходимое этой функции. Поэтому вы не можете сделать это:

get_in(some_struct, [:some_key, :nested_key])

Хорошая новость заключается в том, что структуры имеют предопределённую форму. Поэтому вы можете написать вместо этого:

some_struct.some_key.nested_key

Если get_in/2 может вернуть nil, вы всегда можете использовать сопоставление с образцом для обработки вложенных структур:

case some_struct do
  %{some_key: %{nested_key: value}} -> value
  %{} -> nil
end

if(condition, clauses)Source

Обеспечивает макрос if/2.

Этот макрос ожидает, что первый аргумент будет условием, а второй — списком ключевых слов.

Примеры однострочных выражений

if(foo, do: bar)

В примере выше, value будет возвращено, если condition вычислится как истинное значение (ни false ни nil). В противном случае, будет возвращено else_value.

Можно указать опцию else, чтобы указать обратное:

if(foo, do: bar, else: baz)

Примеры с блоками

Также можно передать блок макросу if/2. Первый пример выше будет преобразован в:

if foo do
  bar
end

Обратите внимание, что condition и else_value становятся разделителями. Второй пример будет преобразован в:

if foo do
  bar
else
  baz
end

Для сравнения более чем двух условий необходимо использовать макрос cond/1.

inspect(term, opts \\ [])Source

@spec inspect(
  Inspect.t(),
  keyword()
) :: String.t()

Проверяет заданный аргумент в соответствии с протоколом Inspect. Второй аргумент — список ключевых слов с параметрами для управления проверкой.

Параметры

inspect/2 принимает список параметров, которые интерпретируются как структура Inspect.Opts. Проверьте документацию для Inspect.Opts, чтобы увидеть поддерживаемые параметры.

Примеры

iex> inspect(:foo)
":foo"

iex> inspect([1, 2, 3, 4, 5], limit: 3)
"[1, 2, 3, ...]"

iex> inspect([1, 2, 3], pretty: true, width: 0)
"[1,\n 2,\n 3]"

iex> inspect("olá" <> <<0>>)
"<<111, 108, 195, 161, 0>>"

iex> inspect("olá" <> <<0>>, binaries: :as_strings)
"\"olá\\0\""

iex> inspect("olá", binaries: :as_binaries)
"<<111, 108, 195, 161>>"

iex> inspect('bar')
"'bar'"

iex> inspect([0 | 'bar'])
"[0, 98, 97, 114]"

iex> inspect(100, base: :octal)
"0o144"

iex> inspect(100, base: :hex)
"0x64"

Обратите внимание, что протокол Inspect не обязательно возвращает действительное представление термина Elixir. В таких случаях инспектируемый результат должен начинаться с #. Например, инспекция функции вернет:

inspect(fn a, b -> a + b end)
#=> #Function<...>

Протокол Inspect может быть изменён для скрытия определённых полей из структур, чтобы они не отображались в логах, результатах инспекции и подобном. Подробнее см. раздел "Производные" документации протокола Inspect.

macro_exported?(module, macro, arity)Source

@spec macro_exported?(module(), atom(), arity()) :: boolean()

Возвращает true, если module загружен и содержит публичную macro с заданным arity, в противном случае false.

Обратите внимание, что эта функция не загружает модуль, если он не загружен. См. Code.ensure_loaded/1 для получения дополнительной информации.

Если module — модуль Erlang (в отличие от модуля Elixir), эта функция всегда возвращает false.

Примеры

iex> macro_exported?(Kernel, :use, 2)
true

iex> macro_exported?(:erlang, :abs, 1)
false

make_ref()Source

@spec make_ref() :: reference()

Возвращает почти уникальную ссылку.

Возвращаемая ссылка появится снова примерно через 2^82 вызовов; следовательно, она достаточно уникальна для практических целей.

Встраивается компилятором.

Примеры

make_ref()
#=> #Reference<0.0.0.135>

match?(pattern, expr)Source

Удобный макрос, проверяющий, совпадает ли правая часть (выражение) с левой частью (шаблоном).

Примеры

iex> match?(1, 1)
true

iex> match?({1, _}, {1, 2})
true

iex> map = %{a: 1, b: 2}
iex> match?(%{a: _}, map)
true

iex> a = 1
iex> match?(^a, 1)
true

match?/2 очень полезен при фильтрации или поиске значения в перечисляемом:

iex> list = [a: 1, b: 2, a: 3]
iex> Enum.filter(list, &match?({:a, _}, &1))
[a: 1, a: 3]

К условиям сопоставления также можно добавлять условия:

iex> list = [a: 1, b: 2, a: 3]
iex> Enum.filter(list, &match?({:a, x} when x < 2, &1))
[a: 1]

Переменные, назначенные в сопоставлении, будут недоступны за пределами вызова функции (в отличие от обычного сопоставления шаблонов с оператором =):

iex> match?(_x, 1)
true
iex> binding()
[]

Значения против шаблонов

Помните, что оператор привязки соответствует значениям, а не шаблонам. Передача переменной в качестве шаблона всегда вернёт true и вызовет предупреждение о том, что переменная не используется:

# don't do this
pattern = %{a: :a}
match?(pattern, %{b: :b})

Аналогично, перемещение выражения из шаблона может больше не сохранять его семантику. Например:

match?([_ | _], [1, 2, 3])
#=> true

pattern = [_ | _]
match?(pattern, [1, 2, 3])
** (CompileError) invalid use of _. "_" represents a value to be ignored in a pattern and cannot be used in expressions

Ещё один пример: карта в качестве шаблона выполняет сопоставление подмножества, но не сразу после назначения переменной:

match?(%{x: 1}, %{x: 1, y: 2})
#=> true

attrs = %{x: 1}
match?(^attrs, %{x: 1, y: 2})
#=> false

Оператор привязки будет проверять, равны ли значения, используя ===/2, а шаблоны имеют свои правила при сопоставлении карт, списков и т. д. Такое поведение не специфично для match?/2. Следующий код также вызывает исключение:

attrs = %{x: 1}
^attrs = %{x: 1, y: 2}
#=> (MatchError) no match of right hand side value: %{x: 1, y: 2}

max(first, second)Source

@spec max(first, second) :: first | second when first: term(), second: term()

Возвращает наибольшее из двух заданных терминов в соответствии с их структурным сравнением.

Если термины сравниваются как равные, возвращается первый.

Выполняется структурное сравнение, где все термины Elixir могут быть сравнены друг с другом. Дополнительную информацию см. в разделе «Структурное сравнение».

Встраивается компилятором.

Примеры

iex> max(1, 2)
2
iex> max(:a, :b)
:b

min(first, second)Source

@spec min(first, second) :: first | second when first: term(), second: term()

Возвращает наименьшее из двух заданных терминов в соответствии с их структурным сравнением.

Если термины сравниваются как равные, возвращается первый.

Выполняется структурное сравнение, где все термины Elixir могут быть сравнены друг с другом. Дополнительную информацию см. в разделе «Структурное сравнение».

Встраивается компилятором.

Примеры

iex> min(1, 2)
1
iex> min("foo", "bar")
"bar"

pop_in(path)Source

Удаляет ключ из вложенной структуры по заданному path.

Это аналогично pop_in/2, за исключением того, что путь извлекается с помощью макроса, а не передаётся в виде списка. Например:

pop_in(opts[:foo][:bar])

Эквивалентно:

pop_in(opts, [:foo, :bar])

Обратите внимание, что для работы этого макроса весь путь должен быть всегда виден этому макросу. Дополнительную информацию о поддерживаемых выражениях пути см. в документации get_and_update_in/2.

Примеры

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> pop_in(users["john"][:age])
{27, %{"john" => %{}, "meg" => %{age: 23}}}

iex> users = %{john: %{age: 27}, meg: %{age: 23}}
iex> pop_in(users.john[:age])
{27, %{john: %{}, meg: %{age: 23}}}

В случае если какое-либо значение возвращает nil, его ключ будет удалён, и удаление будет считаться успешным.

pop_in(data, keys)Source

@spec pop_in(data, [Access.get_and_update_fun(term(), data) | term(), ...]) ::
  {term(), data}
when data: Access.container()

Удаляет ключ из данной вложенной структуры.

Использует протокол Access для обхода структур в соответствии с заданным keys, если key не является функцией. Если ключ является функцией, она будет вызвана согласно get_and_update_in/3.

Примеры

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> pop_in(users, ["john", :age])
{27, %{"john" => %{}, "meg" => %{age: 23}}}

В случае если какое-либо значение возвращает nil, его ключ будет удалён, и удаление будет считаться успешным.

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> pop_in(users, ["jane", :age])
{nil, %{"john" => %{age: 27}, "meg" => %{age: 23}}}

put_elem(tuple, index, value)Source

@spec put_elem(tuple(), non_neg_integer(), term()) :: tuple()

Заменяет value на заданный нулевой индекс в tuple.

Встраивается компилятором.

Примеры

iex> tuple = {:foo, :bar, 3}
iex> put_elem(tuple, 0, :baz)
{:baz, :bar, 3}

put_in(path, value)Source

Вставляет значение во вложенную структуру по заданному path.

Аналогично put_in/3, за исключением того, что путь извлекается с помощью макроса, а не передаётся в виде списка. Например:

put_in(opts[:foo][:bar], :baz)

Эквивалентно:

put_in(opts, [:foo, :bar], :baz)

Это также работает с вложенными структурами и способом указания путей struct.path.to.value:

put_in(struct.foo.bar, :baz)

Обратите внимание, что для работы этого макроса весь путь должен быть всегда виден этому макросу. Дополнительную информацию о поддерживаемых выражениях пути см. в документации get_and_update_in/2.

Примеры

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> put_in(users["john"][:age], 28)
%{"john" => %{age: 28}, "meg" => %{age: 23}}

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> put_in(users["john"].age, 28)
%{"john" => %{age: 28}, "meg" => %{age: 23}}

put_in(data, keys, value)Source

@spec put_in(Access.t(), [term(), ...], term()) :: Access.t()

Вставляет значение во вложенную структуру.

Использует модуль Access для обхода структур в соответствии с заданным keys, если key не является функцией. Если ключ является функцией, она будет вызвана согласно get_and_update_in/3.

Примеры

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> put_in(users, ["john", :age], 28)
%{"john" => %{age: 28}, "meg" => %{age: 23}}

Если какое-либо промежуточное значение равно nil, будет выброшено исключение:

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> put_in(users, ["jane", :age], "oops")
** (ArgumentError) could not put/update key :age on a nil value
END_OF_DOCUMENT_MARKER

raise(message)Source

Вызывает исключение.

Если message является строкой, генерирует исключение RuntimeError с указанным сообщением.

Если message является атомом, вызывает raise/2 с атомом в качестве первого аргумента и [] в качестве второго.

Если message является структурой исключения, она вызывается как есть.

Если message — что-то другое, raise завершится с исключением ArgumentError.

Примеры

iex> raise "oops"
** (RuntimeError) oops

try do
  1 + :foo
rescue
  x in [ArithmeticError] ->
    IO.puts("that was expected")
    raise x
end

raise(exception, attributes)Source

Вызывает исключение.

Вызывает функцию exception/1 для заданного аргумента (который должен быть именем модуля, например, ArgumentError или RuntimeError), передавая attributes для получения структуры исключения.

Любой модуль, содержащий вызов макроса defexception/1, автоматически реализует обработчик Exception.exception/1, ожидаемый функцией raise/2. Дополнительная информация находится в defexception/1.

Примеры

iex> raise(ArgumentError, "Sample")
** (ArgumentError) Sample

reraise(message, stacktrace)Source

Вызывает исключение, сохраняя предыдущий стек вызовов.

Работает как raise/1, но не генерирует новый стек вызовов.

Обратите внимание, что __STACKTRACE__ может использоваться внутри catch/rescue для извлечения текущего стека вызовов.

Примеры

try do
  raise "oops"
rescue
  exception ->
    reraise exception, __STACKTRACE__
end

reraise(exception, attributes, stacktrace)Source

Вызывает исключение, сохраняя предыдущий стек вызовов.

reraise/3 работает как reraise/2, за исключением того, что аргументы передаются функции exception/1 так, как описано в raise/2.

Примеры

try do
  raise "oops"
rescue
  exception ->
    reraise WrapperError, [exception: exception], __STACKTRACE__
end

send(dest, message)Source

@spec send(dest :: Process.dest(), message) :: message when message: any()

Отправляет сообщение заданному dest и возвращает переданное сообщение.

dest может быть удалённым или локальным PID, локальным портом, локально зарегистрированным именем или кортежем в виде {registered_name, node} для зарегистрированного имени на другом узле.

Встроен в компилятор.

Примеры

iex> send(self(), :hello)
:hello

sigil_C(term, modifiers)Source

Обрабатывает сигил ~C для списков символов.

Возвращает список символов без интерполяций и без управляющих последовательностей, кроме экранирования закрывающего символа сигила.

Примеры

iex> ~C(foo)
'foo'

iex> ~C(f#{o}o)
'f\#{o}o'

sigil_c(term, modifiers)Source

Обрабатывает сигил ~c для списков символов.

Возвращает список символов, как если бы это была строка в одинарных кавычках, снимая экранирование символов и заменяя интерполяции.

Примеры

iex> ~c(foo)
'foo'

iex> ~c(f#{:o}o)
'foo'

iex> ~c(f\#{:o}o)
'f\#{:o}o'

sigil_D(date_string, modifiers)Source

Обрабатывает сигил ~D для дат.

По умолчанию этот сигил использует встроенный Calendar.ISO, который требует, чтобы даты были написаны в формате ISO8601:

~D[yyyy-mm-dd]

например:

~D[2015-01-13]

Если вы используете альтернативные календари, можно использовать любое представление, главное следовать за представлением пробелом и именем календаря:

~D[SOME-REPRESENTATION My.Alternative.Calendar]

Вариант с маленькой буквой ~d не существует, так как интерполяция и экранирование символов не полезны для сигилов дат.

Дополнительная информация о датах находится в модуле Date.

Примеры

iex> ~D[2015-01-13]
~D[2015-01-13]

sigil_N(naive_datetime_string, modifiers)Source

Обрабатывает сигил ~N для наивных дат и времени.

По умолчанию этот сигил использует встроенный Calendar.ISO, который требует, чтобы наивные даты и время были написаны в формате ISO8601:

~N[yyyy-mm-dd hh:mm:ss]
~N[yyyy-mm-dd hh:mm:ss.ssssss]
~N[yyyy-mm-ddThh:mm:ss.ssssss]

например:

~N[2015-01-13 13:00:07]
~N[2015-01-13T13:00:07.123]

Если вы используете альтернативные календари, можно использовать любое представление, главное следовать за представлением пробелом и именем календаря:

~N[SOME-REPRESENTATION My.Alternative.Calendar]

Вариант с маленькой буквой ~n не существует, так как интерполяция и экранирование символов не полезны для сигилов дат и времени.

Дополнительная информация о наивных датах и времени находится в модуле NaiveDateTime.

Примеры

iex> ~N[2015-01-13 13:00:07]
~N[2015-01-13 13:00:07]
iex> ~N[2015-01-13T13:00:07.001]
~N[2015-01-13 13:00:07.001]

sigil_R(term, modifiers)Source

Обрабатывает сигил ~R для регулярных выражений.

Возвращает шаблон регулярного выражения без интерполяций и без экранирования символов. Он всё ещё поддерживает экранирование токенов Regex (например, экранирование + или ?) и требует экранирования закрывающего символа сигила, если он встречается в регулярном выражении.

Дополнительная информация о регулярных выражениях находится в модуле Regex.

Примеры

iex> Regex.match?(~R(f#{1,3}o), "f#o")
true

sigil_r(term, modifiers)Source

Обрабатывает сигил ~r для регулярных выражений.

Возвращает шаблон регулярного выражения, снимая экранирование символов и заменяя интерполяции.

Дополнительная информация о регулярных выражениях находится в модуле Regex.

Примеры

iex> Regex.match?(~r/foo/, "foo")
true

iex> Regex.match?(~r/a#{:b}c/, "abc")
true

Хотя сигил ~r позволяет использовать скобки и квадратные скобки в качестве разделителей, предпочтительнее использовать " или / для избежания конфликтов экранирования с зарезервированными символами регулярных выражений.

sigil_S(term, modifiers)Source

Обрабатывает сигил ~S для строк.

Возвращает строку без интерполяций и без экранирования символов, кроме экранирования закрывающего символа сигила.

Примеры

iex> ~S(foo)
"foo"
iex> ~S(f#{o}o)
"f\#{o}o"
iex> ~S(\o/)
"\\o/"

Однако, если вы хотите повторно использовать сам символ сигила в строке, вам нужно экранировать его:

iex> ~S((\))
"()"

sigil_s(term, modifiers)Source

Обрабатывает сигил ~s для строк.

Возвращает строку, как если бы это была строка в двойных кавычках, снимая экранирование символов и заменяя интерполяции.

Примеры

iex> ~s(foo)
"foo"

iex> ~s(f#{:o}o)
"foo"

iex> ~s(f\#{:o}o)
"f\#{:o}o"

sigil_T(time_string, modifiers)Source

Обрабатывает сигил ~T для временных значений.

По умолчанию этот сигил использует встроенный Calendar.ISO, который требует, чтобы время было записано в формате ISO8601:

~T[hh:mm:ss]
~T[hh:mm:ss.ssssss]

например:

~T[13:00:07]
~T[13:00:07.123]

Если вы используете альтернативные календари, можно использовать любое представление, главное следовать за представлением пробелом и именем календаря:

~T[SOME-REPRESENTATION My.Alternative.Calendar]

Вариант с маленькой буквой ~t не существует, так как интерполяция и экранирование символов не полезны для сигилов времени.

Дополнительная информация о времени находится в модуле Time.

Примеры

iex> ~T[13:00:07]
~T[13:00:07]
iex> ~T[13:00:07.001]
~T[13:00:07.001]

sigil_U(datetime_string, modifiers)Source

Обрабатывает сигил ~U для создания объекта UTC DateTime.

По умолчанию, этот сигил использует встроенный Calendar.ISO, который требует, чтобы даты и времена UTC были записаны в формате ISO8601:

~U[yyyy-mm-dd hh:mm:ssZ]
~U[yyyy-mm-dd hh:mm:ss.ssssssZ]
~U[yyyy-mm-ddThh:mm:ss.ssssss+00:00]

например:

~U[2015-01-13 13:00:07Z]
~U[2015-01-13T13:00:07.123+00:00]

Если вы используете альтернативные календари, можно использовать любое представление, но необходимо указать его, добавив после значения пробел и имя календаря:

~U[SOME-REPRESENTATION My.Alternative.Calendar]

Указанное datetime_string значение должно содержать смещение "Z" или "00:00", указывающее на UTC, иначе произойдёт ошибка.

Нижний регистр ~u варианта не существует, так как символы интерполяции и экранирования не используются в сигилах для дат и времён.

Дополнительную информацию о датах и временах можно найти в модуле DateTime.

Примеры

iex> ~U[2015-01-13 13:00:07Z]
~U[2015-01-13 13:00:07Z]
iex> ~U[2015-01-13T13:00:07.001+00:00]
~U[2015-01-13 13:00:07.001Z]

sigil_W(term, modifiers)Source

Обрабатывает сигил ~W для списка слов.

Возвращает список «слов», разделённых пробелами, без интерполяции и без экранирования символов, за исключением экранирования символа закрытия сигила.

Модификаторы

  • s: слова в списке — строки (по умолчанию)
  • a: слова в списке — атомы
  • c: слова в списке — списки символов

Примеры

iex> ~W(foo #{bar} baz)
["foo", "\#{bar}", "baz"]

sigil_w(term, modifiers)Source

Обрабатывает сигил ~w для списка слов.

Возвращает список «слов», разделённых пробелами. Деэкранирование и интерполяция символов происходят для каждого слова.

Модификаторы

  • s: слова в списке — строки (по умолчанию)
  • a: слова в списке — атомы
  • c: слова в списке — списки символов

Примеры

iex> ~w(foo #{:bar} baz)
["foo", "bar", "baz"]

iex> ~w(foo #{" bar baz "})
["foo", "bar", "baz"]

iex> ~w(--source test/enum_test.exs)
["--source", "test/enum_test.exs"]

iex> ~w(foo bar baz)a
[:foo, :bar, :baz]

iex> ~w(foo bar baz)c
['foo', 'bar', 'baz']

spawn(fun)Source

@spec spawn((() -> any())) :: pid()

Запускает заданную функцию и возвращает её PID.

Разработчики обычно не используют функции spawn, а вместо этого используют абстракции, такие как Task, GenServer и Agent, построенные поверх spawn, которые запускают процессы с большей удобством с точки зрения интроспекции и отладки.

См. модуль Process для получения дополнительных функций, связанных с процессами.

Анонимная функция принимает 0 аргументов и может возвращать любое значение.

Встроенная компилятором.

Примеры

current = self()
child = spawn(fn -> send(current, {self(), 1 + 2}) end)

receive do
  {^child, 3} -> IO.puts("Received 3 back")
end

spawn(module, fun, args)Source

@spec spawn(module(), atom(), list()) :: pid()

Запускает заданную функцию fun из заданного модуля module, передавая ей заданные аргументы args, и возвращает её PID.

Разработчики обычно не используют функции spawn, а вместо этого используют абстракции, такие как Task, GenServer и Agent, построенные поверх spawn, которые запускают процессы с большей удобством с точки зрения интроспекции и отладки.

См. модуль Process для получения дополнительных функций, связанных с процессами.

Встроенная компилятором.

Примеры

spawn(SomeModule, :function, [1, 2, 3])

spawn_link(fun)Source

@spec spawn_link((() -> any())) :: pid()

Запускает заданную функцию, связывает её с текущим процессом и возвращает её PID.

Разработчики обычно не используют функции spawn, а вместо этого используют абстракции, такие как Task, GenServer и Agent, построенные поверх spawn, которые запускают процессы с большей удобством с точки зрения интроспекции и отладки.

См. модуль Process для получения дополнительных функций, связанных с процессами. Для получения дополнительной информации о связывании, см. Process.link/1.

Анонимная функция принимает 0 аргументов и может возвращать любое значение.

Встроенная компилятором.

Примеры

current = self()
child = spawn_link(fn -> send(current, {self(), 1 + 2}) end)

receive do
  {^child, 3} -> IO.puts("Received 3 back")
end

spawn_link(module, fun, args)Source

@spec spawn_link(module(), atom(), list()) :: pid()

Запускает заданную функцию fun из заданного модуля module, передавая ей заданные аргументы args, связывает её с текущим процессом и возвращает её PID.

Разработчики обычно не используют функции spawn, а вместо этого используют абстракции, такие как Task, GenServer и Agent, построенные поверх spawn, которые запускают процессы с большей удобством с точки зрения интроспекции и отладки.

См. модуль Process для получения дополнительных функций, связанных с процессами. Для получения дополнительной информации о связывании, см. Process.link/1.

Встроенная компилятором.

Примеры

spawn_link(SomeModule, :function, [1, 2, 3])

spawn_monitor(fun)Source

@spec spawn_monitor((() -> any())) :: {pid(), reference()}

Запускает заданную функцию, отслеживает её и возвращает её PID и ссылку на отслеживание.

Разработчики обычно не используют функции spawn, а вместо этого используют абстракции, такие как Task, GenServer и Agent, построенные поверх spawn, которые запускают процессы с большей удобством с точки зрения интроспекции и отладки.

См. модуль Process для получения дополнительных функций, связанных с процессами.

Анонимная функция принимает 0 аргументов и может возвращать любое значение.

Встроенная компилятором.

Примеры

current = self()
spawn_monitor(fn -> send(current, {self(), 1 + 2}) end)

spawn_monitor(module, fun, args)Source

@spec spawn_monitor(module(), atom(), list()) :: {pid(), reference()}

Запускает заданный модуль и функцию, передавая заданные аргументы, отслеживает её и возвращает её PID и ссылку на отслеживание.

Разработчики обычно не используют функции spawn, а вместо этого используют абстракции, такие как Task, GenServer и Agent, построенные поверх spawn, которые запускают процессы с большей удобством с точки зрения интроспекции и отладки.

См. модуль Process для получения дополнительных функций, связанных с процессами.

Встроенная компилятором.

Примеры

spawn_monitor(SomeModule, :function, [1, 2, 3])

struct(struct, fields \\ [])Source

@spec struct(module() | struct(), Enumerable.t()) :: struct()

Создаёт и обновляет структуру.

Аргумент struct может быть атомом (который определяет defstruct) или самой структурой. Второй аргумент — любой Enumerable, который генерирует пары ключ-значение (кортежи из двух элементов) во время перебора.

Ключи в Enumerable, которые не существуют в структуре, автоматически отбрасываются. Обратите внимание, что ключи должны быть атомами, так как только атомы разрешены при определении структуры. Если ключи в Enumerable дублируются, будет использоваться последняя запись (то же поведение, что и у Map.new/1).

Эта функция полезна для динамического создания и обновления структур, а также для преобразования карт в структуры; в последнем случае просто вставка соответствующего :__struct__ поля в карту может быть недостаточно, и вместо этого следует использовать struct/2.

Примеры

defmodule User do
  defstruct name: "john"
end

struct(User)
#=> %User{name: "john"}

opts = [name: "meg"]
user = struct(User, opts)
#=> %User{name: "meg"}

struct(user, unknown: "value")
#=> %User{name: "meg"}

struct(User, %{name: "meg"})
#=> %User{name: "meg"}

# String keys are ignored
struct(User, %{"name" => "meg"})
#=> %User{name: "john"}
END_OF_DOCUMENT_MARKER

struct!(struct, fields \\ [])Source

@spec struct!(module() | struct(), Enumerable.t()) :: struct()

Аналогично struct/2, но проверяет валидность ключей.

Функция struct!/2 эмулирует поведение структур на этапе компиляции. Это означает, что:

  • при создании структуры, как в struct!(SomeStruct, key: :value), она эквивалентна %SomeStruct{key: :value}, и, следовательно, эта функция проверит, относится ли каждая пара ключ-значение к структуре. Если структура требует какой-либо ключ через @enforce_keys, они также будут проверены;

  • при обновлении структуры, как в struct!(%SomeStruct{}, key: :value), она эквивалентна %SomeStruct{struct | key: :value}, и, следовательно, эта функция проверит, относится ли каждая пара ключ-значение к структуре. Однако обновление структур не требует проверки ключей, так как ключи проверяются только при создании;

tap(value, fun)Source

Передает первый аргумент, value, во второй аргумент, функцию fun, и возвращает value само.

Полезно для запуска синхронных побочных эффектов в конвейере, используя оператор |>/2.

Примеры

iex> tap(1, fn x -> x + 1 end)
1

Чаще всего это используется в конвейерах, используя оператор |>/2. Например, предположим, что вам нужно проверить часть структуры данных. Вы могли бы написать:

%{a: 1}
|> Map.update!(:a, & &1 + 2)
|> tap(&IO.inspect(&1.a))
|> Map.update!(:a, & &1 * 2)

then(value, fun)Source

Передает первый аргумент, value, во второй аргумент, функцию fun, и возвращает результат вызова fun.

Другими словами, она вызывает функцию fun с value в качестве аргумента и возвращает её результат.

Это чаще всего используется в конвейерах, используя оператор |>/2, позволяя передавать значение в функцию, не ограничиваясь её первым аргументом.

Примеры

iex> 1 |> then(fn x -> x * 2 end)
2

iex> 1 |> then(fn x -> Enum.drop(["a", "b", "c"], x) end)
["b", "c"]

throw(term)Source

@spec throw(term()) :: no_return()

Нелокальное возвращение из функции.

Использование throw/1 обычно не рекомендуется, так как оно позволяет функции выйти за пределы своего обычного потока выполнения, что может затруднить чтение кода. Кроме того, все брошенные значения должны быть перехвачены try/catch. Смотрите try/1 для получения дополнительной информации.

Встраивается компилятором.

to_charlist(term)Source

Преобразует заданный термин в charlist в соответствии с протоколом List.Chars.

Примеры

iex> to_charlist(:foo)
'foo'

to_string(term)Source

Преобразует аргумент в строку в соответствии с протоколом String.Chars.

Эта функция вызывается при интерполяции строк.

Примеры

iex> to_string(:foo)
"foo"

unless(condition, clauses)Source

Обеспечивает макрос unless.

Этот макрос вычисляет и возвращает блок do, переданный во втором аргументе, если condition вычисляется как ложное значение (false или nil). В противном случае он возвращает значение блока else, если он присутствует, или nil, если нет.

См. также if/2.

Примеры

iex> unless(Enum.empty?([]), do: "Hello")
nil

iex> unless(Enum.empty?([1, 2, 3]), do: "Hello")
"Hello"

iex> unless Enum.sum([2, 2]) == 5 do
...>   "Math still works"
...> else
...>   "Math is broken"
...> end
"Math still works"

update_in(path, fun)Source

Обновляет вложенную структуру с помощью данной функции path.

Это похоже на update_in/3, за исключением того, что путь извлекается с помощью макроса, а не в виде списка. Например:

update_in(opts[:foo][:bar], &(&1 + 1))

Эквивалентно:

update_in(opts, [:foo, :bar], &(&1 + 1))

Это также работает с вложенными структурами и способом указания путей через struct.path.to.value:

update_in(struct.foo.bar, &(&1 + 1))

Обратите внимание, что для работы этого макроса полный путь должен быть всегда виден макросу. Дополнительную информацию о поддерживаемых выражениях путей можно найти в документации get_and_update_in/2.

Примеры

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> update_in(users["john"][:age], &(&1 + 1))
%{"john" => %{age: 28}, "meg" => %{age: 23}}

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> update_in(users["john"].age, &(&1 + 1))
%{"john" => %{age: 28}, "meg" => %{age: 23}}

update_in(data, keys, fun)Source

@spec update_in(Access.t(), [term(), ...], (term() -> term())) :: Access.t()

Обновляет ключ вложенной структуры.

Использует модуль Access для обхода структур в соответствии с заданным keys, если key не является функцией. Если ключ является функцией, она будет вызвана как указано в get_and_update_in/3.

data — это вложенная структура (т. е. карта, список ключевых слов или структура, реализующая поведение Access). Аргумент fun получает значение key (или nil, если key отсутствует), а результат заменяет значение в структуре.

Примеры

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> update_in(users, ["john", :age], &(&1 + 1))
%{"john" => %{age: 28}, "meg" => %{age: 23}}

Обратите внимание, что текущее значение, переданное анонимной функции, может быть nil. Если любое из промежуточных значений равно nil, будет возбуждено исключение:

iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> update_in(users, ["jane", :age], & &1 + 1)
** (ArgumentError) could not put/update key :age on a nil value

use(module, opts \\ [])Source

Использует данный модуль в текущем контексте.

При вызове:

use MyModule, some: :options

Elixir вызовет MyModule.__using__/1, передав второй аргумент use в качестве своего аргумента. Поскольку __using__/1 обычно является макросом, применяются все обычные правила для макросов, а её возвращаемое значение должно быть цитируемым кодом, который затем вставляется туда, где вызывается use/2.

Примечание: use MyModule работает как точка вставки кода в вызывающий код. Учитывая, что вызывающий код use MyModule имеет небольшой контроль над тем, как вставляется код, use/2 следует использовать с осторожностью. Если возможно, избегайте использования в пользу import/2 или alias/2 в случае возможности.

Примеры

Например, для написания тестовых случаев, используя фреймворк ExUnit, предоставляемый с Elixir, разработчик должен использовать ExUnit.Case модуль:

defmodule AssertionTest do
  use ExUnit.Case, async: true

  test "always pass" do
    assert true
  end
end

В этом примере Elixir вызовет макрос __using__/1 в модуле ExUnit.Case с списком ключевых слов [async: true] в качестве аргумента.

Другими словами, use/2 преобразуется в:

defmodule AssertionTest do
  require ExUnit.Case
  ExUnit.Case.__using__(async: true)

  test "always pass" do
    assert true
  end
end

где ExUnit.Case определяет макрос __using__/1:

defmodule ExUnit.Case do
  defmacro __using__(opts) do
    # do something with opts
    quote do
      # return some code to inject in the caller
    end
  end
end

Рекомендации по использованию

__using__/1 обычно используется, когда необходимо установить некоторое состояние (через атрибуты модуля) или обратные вызовы (например, @before_compile, см. документацию по Module для получения дополнительной информации) в вызывающий код.

__using__/1 также может использоваться для алиасирования, требования или импорта функциональности из других модулей:

defmodule MyModule do
  defmacro __using__(_opts) do
    quote do
      import MyModule.Foo
      import MyModule.Bar
      import MyModule.Baz

      alias MyModule.Repo
    end
  end
end

Однако не предоставляйте __using__/1 , если всё, что оно делает, это импортирует, алиасит или требует сам модуль. Например, избегайте этого:

defmodule MyModule do
  defmacro __using__(_opts) do
    quote do
      import MyModule
    end
  end
end

В таких случаях разработчики должны вместо этого импортировать или алиасить модуль напрямую, чтобы они могли настроить их по своему желанию, без косвенности через use/2.

Наконец, разработчики также должны избегать определения функций внутри обратного вызова __using__/1 , за исключением тех случаев, когда эти функции являются реализацией по умолчанию ранее определенного @callback или являются функциями, предназначенными для переопределения (см. defoverridable/1). Даже в этих случаях определение функций следует рассматривать как «последний выход».

END_OF_DOCUMENT_MARKER

var!(var, context \\ nil)Source

Помечает, что данная переменная не должна подвергаться гигиенизации.

Этот макрос ожидает переменную и обычно вызывается внутри Kernel.SpecialForms.quote/2 для обозначения того, что переменная не должна подвергаться гигиенизации. См. Kernel.SpecialForms.quote/2 для получения дополнительной информации.

Примеры

iex> Kernel.var!(example) = 1
1
iex> Kernel.var!(example)
1

left |> rightSource

Оператор конвейера.

Этот оператор вводит выражение слева в качестве первого аргумента вызова функции справа.

Примеры

iex> [1, [2], 3] |> List.flatten()
[1, 2, 3]

Приведённый выше пример эквивалентен вызову List.flatten([1, [2], 3]).

Оператор |>/2 в основном полезен, когда требуется выполнить серию операций, напоминающих конвейер:

iex> [1, [2], 3] |> List.flatten() |> Enum.map(fn x -> x * 2 end)
[2, 4, 6]

В примере выше список [1, [2], 3] передаётся в качестве первого аргумента функции List.flatten/1, затем сглаженный список передаётся в качестве первого аргумента функции Enum.map/2, которая удваивает каждый элемент списка.

Другими словами, данное выражение просто переводится в:

Enum.map(List.flatten([1, [2], 3]), fn x -> x * 2 end)

Возможные ошибки

При использовании оператора конвейера существует две распространённые ошибки.

Первая связана с приоритетом операторов. Например, следующее выражение:

String.graphemes "Hello" |> Enum.reverse

Переводится в:

String.graphemes("Hello" |> Enum.reverse())

что приводит к ошибке, так как протокол Enumerable не определён для двоичных данных. Добавление явных скобок устраняет неоднозначность:

String.graphemes("Hello") |> Enum.reverse()

Или, ещё лучше:

"Hello" |> String.graphemes() |> Enum.reverse()

Вторая ограничение заключается в том, что Elixir всегда применяет конвейер к вызову функции. Поэтому, чтобы применить конвейер к анонимной функции, необходимо вызвать её:

some_fun = &Regex.replace(~r/l/, &1, "L")
"Hello" |> some_fun.()

В качестве альтернативы, можно использовать then/2 для того же результата:

some_fun = &Regex.replace(~r/l/, &1, "L")
"Hello" |> then(some_fun)

then/2 чаще всего используется, когда вы хотите применить конвейер к функции, но значение ожидается вне первого аргумента, как показано выше. Заменив some_fun его значением, получаем:

"Hello" |> then(&Regex.replace(~r/l/, &1, "L"))

left || rightSource

Логический оператор «или».

Обеспечивает оператор короткого замыкания, который оценивает и возвращает второе выражение только в том случае, если первое выражение не оценивается как истинное значение (то есть, оно равно либо nil или false). В противном случае возвращает первое выражение.

Запрещено в операторах-условиях.

Примеры

iex> Enum.empty?([1]) || Enum.empty?([1])
false

iex> List.first([]) || true
true

iex> Enum.empty?([1]) || 1
1

iex> Enum.empty?([]) || throw(:bad)
true

Обратите внимание, что, в отличие от or/2, этот оператор принимает любое выражение в качестве первого аргумента, а не только булевы значения.

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.14.1/Kernel.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API