Исходный код Запись
Модуль для работы с записями, их определения и импорта.
Записи — это просто кортежи, где первый элемент — атом:
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
Рефлексия
Тег записи и её поля хранятся в качестве метаданных в блоке «Документация» макроса определения записи. Вы можете получить документацию для модуля, вызвав Code.fetch_docs/1.
Краткое описание
Защита
- is_record(данные)
Проверяет, является ли заданное
dataзаписью.- is_record(данные, тип)
Проверяет, является ли заданное
dataзаписью типаkind.
Функции
- defrecord(имя, тег \\ nil, kv)
Определяет набор макросов для создания, доступа и сопоставления с образцом для записи.
- defrecordp(имя, тег \\ nil, kv)
Аналогично
defrecord/3, но генерирует частные макросы.- extract(имя, параметры)
Извлекает информацию о записи из файла Erlang.
- extract_all(параметры)
Извлекает всю информацию о всех записях из файла Erlang.
Защита
is_record(данные)Исходный код
Проверяет, является ли заданное data записью.
Это реализовано как макрос, поэтому его можно использовать в защитных условиях.
Примеры
Record.is_record({User, "john", 27})
#=> true
Record.is_record({})
#=> 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(имя, параметры)Исходный код
@spec 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(параметры)Исходный код
@spec extract_all(keyword()) :: [{name :: atom(), keyword()}] Извлекает всю информацию о всех записях из файла Erlang.
Возвращает список ключевых слов кортежей {record_name, fields}, где record_name — имя извлечённой записи, а fields — список кортежей {field, value} полей для этой записи.
Параметры
Принимает те же параметры, что и Record.extract/2.
© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.18.1/Record.html