Запись
Модуль для работы с записями, определения и импорта записей.
Записи — это просто кортежи, где первый элемент — атом:
iex> Record.is_record({User, "john", 27})
true Этот модуль предоставляет удобства для работы с записями во время компиляции, где имена полей во время компиляции используются для манипулирования кортежами, обеспечивая быстрые операции над компактной структурой кортежей.
В Elixir записи в основном используются в двух ситуациях:
- для работы с короткими внутренними данными
- для взаимодействия с записями Erlang
Макросы defrecord/3 и defrecordp/3 могут быть использованы для создания записей, а extract/2 и extract_all/1 — для извлечения записей из файлов Erlang.
Типы
Типы могут быть определены для кортежей с помощью макроса record/2 (доступен только в typespec). Этот макрос будет развернут в кортеж, как показано в примере ниже:
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 Обзор
Защитные условия
- is_record(данные)
Проверяет, является ли данная
dataзаписью.- is_record(данные, вид)
Проверяет, является ли данная
dataзаписью видаkind.
Функции
- defrecord(имя, тег \\ nil, kv)
Определяет набор макросов для создания, доступа и сопоставления по шаблону с записью.
- defrecordp(имя, тег \\ nil, kv)
Аналогично
defrecord/3, но генерирует закрытые макросы.- extract(имя, opts)
Извлекает информацию о записи из файла Erlang.
- extract_all(opts)
Извлекает всю информацию о всех записях из файла Erlang.
Защитные условия
is_record(данные)
(макрос) Проверяет, является ли данная data записью.
Это реализовано как макрос, чтобы его можно было использовать в защитных условиях.
Примеры
iex> record = {User, "john", 27}
iex> Record.is_record(record)
true
iex> tuple = {}
iex> Record.is_record(tuple)
false is_record(данные, вид)
(макрос) Проверяет, является ли данная data записью вида kind.
Это реализовано как макрос, чтобы его можно было использовать в защитных условиях.
Примеры
iex> record = {User, "john", 27}
iex> Record.is_record(record, User)
true Функции
defrecord(имя, тег \\ 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 использует имя записи в качестве первого элемента кортежа (тега). Однако можно указать другой тег при определении записи, как в следующем примере, в котором мы используем Customer в качестве второго аргумента defrecord/3:
defmodule User do
require Record
Record.defrecord(:user, Customer, name: nil)
end
require User
User.user() #=> {Customer, 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(имя, тег \\ nil, kv)
(макрос) Аналогично defrecord/3, но генерирует закрытые макросы.
extract(имя, opts)
extract(name :: atom(), keyword()) :: keyword()
Извлекает информацию о записи из файла Erlang.
Возвращает цитируемое выражение, содержащее поля в виде списка кортежей.
name, которое является именем извлеченной записи, должно быть атомом во время компиляции.
Параметры
Эта функция принимает следующие параметры, которые взаимоисключающие (т.е., только один из них может быть использован в одном вызове):
-
:from- (бинарное представление пути к файлу) путь к файлу Erlang, содержащий определение записи для извлечения; с этим параметром функция использует тот же поиск пути, что и атрибут-include, используемый в модулях Erlang. -
:from_lib- (бинарное представление пути к файлу) путь к файлу Erlang, содержащий определение записи для извлечения; с этим параметром функция использует тот же поиск пути, что и атрибут-include_lib, используемый в модулях Erlang. -
:includes- (список директорий в виде бинарных данных) если извлекаемая запись зависит от относительных включений, этот параметр позволяет разработчикам указать директорию, в которой существуют эти относительные включения. -
:macros- (список ключевых слов имен и значений макросов) если извлекаемая запись зависит от значений макросов, этот параметр позволяет установить значение этих макросов.
Ожидается, что эти параметры будут литералами (включая бинарные значения) во время компиляции.
Примеры
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)
extract_all(keyword()) :: [{name :: atom(), keyword()}] Извлекает всю информацию о всех записях из файла Erlang.
Возвращает список ключевых слов кортежей {record_name, fields}, где record_name — имя извлеченной записи, а fields — список кортежей {field, value} , представляющих поля для этой записи.
Параметры
Эта функция принимает следующие параметры, которые взаимоисключающие (т.е., только один из них может быть использован в одном вызове):
-
:from- (бинарное представление пути к файлу) путь к файлу Erlang, содержащий определения записей для извлечения; с этим параметром функция использует тот же поиск пути, что и атрибут-include, используемый в модулях Erlang. -
:from_lib- (бинарное представление пути к файлу) путь к файлу Erlang, содержащий определения записей для извлечения; с этим параметром функция использует тот же поиск пути, что и атрибут-include_lib, используемый в модулях Erlang.
Ожидается, что эти параметры будут литералами (включая бинарные значения) во время компиляции.
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.8.2/Record.html