Запись
Модуль для работы с записями, определения и импорта записей.
Записи — это просто кортежи, где первый элемент — атом:
iex> Record.is_record {User, "john", 27}
true Этот модуль предоставляет удобства для работы с записями во время компиляции, где имена полей времени компиляции используются для управления кортежами, обеспечивая быстрые операции над компактной структурой кортежей.
В Elixir записи в основном используются в двух ситуациях:
- для работы с короткими внутренними данными
- для взаимодействия с записями Erlang
Макросы defrecord/3 и defrecordp/3 могут использоваться для создания записей, а extract/2 и extract_all/1 могут использоваться для извлечения записей из файлов Erlang.
Типы
Типы могут быть определены для кортежей с помощью макроса record/2 (доступен только в описаниях типов). Этот макрос будет расширяться до кортежа, как показано в примере ниже:
defmodule MyModule do
require Record
Record.defrecord :user, name: "john", age: 25
@type user :: record(:user, name: String.t, age: integer)
# expands to: "@type user :: {:user, String.t, integer}"
end Обзор
Функции
- defrecord(name, tag \\ nil, kv)
-
Определяет набор макросов для создания, доступа и сопоставления с образцом записи
- defrecordp(name, tag \\ nil, kv)
-
То же, что и
defrecord/3, но генерирует приватные макросы - extract(name, opts)
-
Извлекает информацию о записи из файла Erlang
- extract_all(opts)
-
Извлекает всю информацию о записях из файла Erlang
- is_record(data)
-
Проверяет, является ли данная
dataзаписью - is_record(data, kind)
-
Проверяет, является ли данная
dataзаписью типаkind
Функции
defrecord(name, tag \\ nil, kv) (макрос)
Определяет набор макросов для создания, доступа и сопоставления с образцом записи.
Имя сгенерированных макросов будет name (должно быть атомом). tag также является атомом и используется в качестве «тега» для записи (то есть, первого элемента кортежа записи); по умолчанию (если nil), он совпадает с name. kv — это список ключевых слов полей name: default_value для новой записи.
Генерируются следующие макросы:
-
name/0для создания новой записи с значениями по умолчанию для всех полей -
name/1для создания новой записи с заданными полями и значениями, для получения индекса (с нуля) заданного поля в записи или для преобразования заданной записи в список ключевых слов -
name/2для обновления существующей записи с заданными полями и значениями или для доступа к заданному полю в заданной записи
Все эти макросы являются публичными (как определено defmacro).
Примеры использования этих макросов см. в разделе «Примеры».
Примеры
defmodule User do require Record Record.defrecord :user, [name: "meg", age: "25"] end
В примере выше будет определен набор макросов с именем user, но с различными арностью для управления базовой записью.
# Import the module to make the user macros locally available
import User
# To create records
record = user() #=> {:user, "meg", 25}
record = user(age: 26) #=> {:user, "meg", 26}
# To get a field from the record
user(record, :name) #=> "meg"
# To update the record
user(record, age: 26) #=> {:user, "meg", 26}
# To get the zero-based index of the field in record tuple
# (index 0 is occupied by the record "tag")
user(:name) #=> 1
# Convert a record to a keyword list
user(record) #=> [name: "meg", age: 26] Сгенерированные макросы также могут использоваться для сопоставления с образцом записей и привязки переменных во время сопоставления:
record = user() #=> {:user, "meg", 25}
user(name: name) = record
name #=> "meg" По умолчанию Elixir использует имя записи в качестве первого элемента кортежа (тега). Однако можно указать другой тег при определении записи:
defmodule User do
require Record
Record.defrecord :user, User, name: nil
end
require User
User.user() #=> {User, nil} Определение извлеченных записей с анонимными функциями в значениях
Если запись определяет анонимную функцию в значениях по умолчанию, будет поднято исключение ArgumentError. Это может произойти непреднамеренно при определении записи после ее извлечения из библиотеки Erlang, использующей анонимные функции по умолчанию.
Record.defrecord :my_rec, Record.extract(...) #=> ** (ArgumentError) invalid value for record field fun_field, cannot escape #Function<12.90072148/2 in :erl_eval.expr/5>.
Чтобы обойти эту ошибку, переопределите поле с вашей собственной функцией &M.f/a, как показано ниже:
defmodule MyRec do
require Record
Record.defrecord :my_rec, Record.extract(...) |> Keyword.merge(fun_field: &__MODULE__.foo/2)
def foo(bar, baz), do: IO.inspect({bar, baz})
end defrecordp(name, tag \\ nil, kv) (макрос)
То же, что и defrecord/3, но генерирует приватные макросы.
extract(name, opts)
Извлекает информацию о записи из файла Erlang.
Возвращает выражение с котировкой, содержащее поля в виде списка кортежей.
name, имя извлеченной записи, должно быть атомом во время компиляции.
Параметры
Эта функция принимает следующие параметры, которые являются взаимоисключающими (т.е., только один из них может быть использован в одном вызове):
-
:from— (двоичное представление пути к файлу) путь к файлу Erlang, содержащий определение записи для извлечения; с этим параметром функция использует тот же поиск путей, что и атрибут-includeв модулях Erlang. -
:from_lib— (двоичное представление пути к файлу) путь к файлу Erlang, содержащий определение записи для извлечения; с этим параметром функция использует тот же поиск путей, что и атрибут-include_libв модулях Erlang.
Ожидается, что эти параметры будут литералами (включая двоичные значения) во время компиляции.
Примеры
iex> Record.extract(:file_info, from_lib: "kernel/include/file.hrl") [size: :undefined, type: :undefined, access: :undefined, atime: :undefined, mtime: :undefined, ctime: :undefined, mode: :undefined, links: :undefined, major_device: :undefined, minor_device: :undefined, inode: :undefined, uid: :undefined, gid: :undefined]
extract_all(opts)
Извлекает всю информацию о записях из файла Erlang.
Возвращает список ключевых слов кортежей {record_name, fields}, где record_name — имя извлеченной записи, а fields — список кортежей {field, value} полей для этой записи.
Параметры
Эта функция принимает следующие параметры, которые являются взаимоисключающими (т.е., только один из них может быть использован в одном вызове):
-
:from— (двоичное представление пути к файлу) путь к файлу Erlang, содержащий определения записей для извлечения; с этим параметром функция использует тот же поиск путей, что и атрибут-includeв модулях Erlang. -
:from_lib— (двоичное представление пути к файлу) путь к файлу Erlang, содержащий определения записей для извлечения; с этим параметром функция использует тот же поиск путей, что и атрибут-include_libв модулях Erlang.
Ожидается, что эти параметры будут литералами (включая двоичные значения) во время компиляции.
is_record(data) (макрос)
Проверяет, является ли данная data записью.
Это реализовано как макрос, так как он может использоваться в условиях охраны.
Примеры
iex> record = {User, "john", 27}
iex> Record.is_record(record)
true
iex> tuple = {}
iex> Record.is_record(tuple)
false is_record(data, kind) (макрос)
Проверяет, является ли данная data записью типа kind.
Это реализовано как макрос, так как он может использоваться в условиях охраны.
Примеры
iex> record = {User, "john", 27}
iex> Record.is_record(record, User)
true
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.4.5/Record.html