Spec-Zone.ru › Elixir 1.13

Запись

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

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

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.13.4/Record.html

Spec-Zone.ru

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