Spec-Zone.ru › Elixir 1.15

Запись

Модуль для работы с записями, определения и импорта записей.

Записи — это просто кортежи, где первый элемент — атом:

iex> Record.is_record({User, "john", 27})
true

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

В Elixir записи в основном используются в двух ситуациях:

  1. для работы с короткими внутренними данными
  2. для взаимодействия с записями 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

Рефлексия

Список всех записей в модуле, если таковые имеются, может быть получен путем чтения атрибута модуля @__records__. Он возвращает список карт с типом записи, именем, тегом и полями. Атрибут доступен только внутри определения модуля.

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

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 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.15.4/Record.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API