Spec-Zone.ru › Elixir 1.18

Исходный код Модуль поведение

Предоставляет функции для работы с модулями во время компиляции.

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

После компиляции модуля использование многих функций в этом модуле вызовет ошибки, поскольку они не предназначены для проверки данных во время выполнения. Большинство данных во время выполнения можно проверить с помощью функции __info__/1, прикреплённой к каждому скомпилированному модулю.

Атрибуты модуля

Каждый модуль может быть снабжён одним или несколькими атрибутами. Следующие атрибуты в настоящее время определены в Elixir:

@after_compile

Хук, который будет вызван сразу после компиляции текущего модуля. Принимает модуль или {module, function_name}. Смотрите раздел «Обработчики компиляции» ниже.

@after_verify (с версии v1.14.0)

Хук, который будет вызван сразу после проверки текущего модуля на наличие неопределённых функций, устаревших функций и т. д. Принимает модуль или {module, function_name}. Смотрите раздел «Обработчики компиляции» ниже.

@before_compile

Хук, который будет вызван перед компиляцией модуля. Принимает модуль или {module, function_or_macro_name} кортеж. Смотрите раздел «Обработчики компиляции» ниже.

@behaviour

Обратите внимание на британскую орфографию!

Модули могут ссылаться на поведенческие модели для обеспечения реализации требуемых функций с определёнными сигнатурами, определёнными @callback.

Например, можно указать поведенческую модель URI.Parser следующим образом:

defmodule URI.Parser do
  @doc "Defines a default port"
  @callback default_port() :: integer

  @doc "Parses the given URL"
  @callback parse(uri_info :: URI.t()) :: URI.t()
end

А затем модуль может использовать её следующим образом:

defmodule URI.HTTP do
  @behaviour URI.Parser
  def default_port(), do: 80
  def parse(info), do: info
end

Если поведение изменяется или URI.HTTP не реализует один из обратных вызовов, будет выведено предупреждение.

Для подробной документации см. документацию по спецификациям типов поведения.

@impl (с версии v1.5.0)

Для облегчения правильной реализации поведения вы можете необязательно объявить @impl для реализованных обратных вызовов поведения. Это делает обратные вызовы явными и может помочь обнаружить ошибки в вашем коде. Компилятор выведет предупреждения в таких случаях:

  • если вы помечаете функцию @impl, когда эта функция не является обратным вызовом.

  • если вы не помечаете функцию @impl, когда другие функции помечены @impl. Если вы помечаете одну функцию @impl, вы должны пометить все другие обратные вызовы для данного поведения как @impl.

@impl работает на основе контекста. Если вы генерируете функцию через макрос и помечаете её @impl, это не повлияет на модуль, в котором эта функция сгенерирована.

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

Используя @impl, пример выше можно переписать как:

defmodule URI.HTTP do
  @behaviour URI.Parser

  @impl true
  def default_port(), do: 80

  @impl true
  def parse(info), do: info
end

Вы можете передать false, true, или конкретную поведенческую модель в @impl.

defmodule Foo do
  @behaviour Bar
  @behaviour Baz

  # Will warn if neither Bar nor Baz specify a callback named bar/0.
  @impl true
  def bar(), do: :ok

  # Will warn if Baz does not specify a callback named baz/0.
  @impl Baz
  def baz(), do: :ok
end

Код теперь более читаемый, так как теперь ясно, какие функции являются частью вашего API, а какие — реализациями обратных вызовов. Для усиления этой идеи, @impl true автоматически помечает функцию как @doc false, отключая документацию, если @doc не задано явно.

@compile

Определяет параметры для компиляции модуля. Это используется для настройки как Elixir, так и Erlang компиляторов, а также любых других проходов компиляции, добавленных внешними инструментами. Например:

defmodule MyModule do
  @compile {:inline, my_fun: 1}

  def my_fun(arg) do
    to_string(arg)
  end
end

Несколько применений @compile будут накапливаться, а не перезаписывать предыдущие. См. раздел «Параметры компиляции» ниже.

@deprecated (с версии v1.6.0)

Предоставляет причину устаревания функции. Например:

defmodule Keyword do
  @deprecated "Use Kernel.length/1 instead"
  def size(keyword) do
    length(keyword)
  end
end

Компилятор Mix автоматически обнаруживает вызовы устаревших модулей и выводит предупреждения во время компиляции.

Использование атрибута @deprecated также будет отражено в документации данной функции и макроса. Вы можете выбрать между атрибутом @deprecated и метаданными документации для предоставления жёстких устаревших функций (с предупреждениями) и мягких устаревших функций (без предупреждений):

Это мягкое устаревание, так как оно просто отмечает документацию как устаревшую:

@doc deprecated: "Use Kernel.length/1 instead"
def size(keyword)

Это жёсткое устаревание, так как оно выводит предупреждения и отмечает документацию как устаревшую:

@deprecated "Use Kernel.length/1 instead"
def size(keyword)

В настоящее время @deprecated поддерживает только функции и макросы. Однако вы можете использовать ключ :deprecated в метаданных аннотаций для аннотации документации модулей, типов и обратных вызовов.

Мы рекомендуем использовать эту функцию с осторожностью, особенно авторам библиотек. Устаревание кода всегда увеличивает нагрузку на пользователей библиотек. Мы также рекомендуем поддерживать устаревшую функциональность в течение длительного времени даже после устаревания, давая разработчикам достаточно времени для обновления (за исключением случаев, когда сохранение устаревшего API нежелательно, например, при наличии проблем с безопасностью).

@doc и @typedoc

Предоставляет документацию для сущности, следующей за атрибутом. @doc используется с функцией, макросом, обратным вызовом или макрообратным вызовом, а @typedoc — с типом (публичным или непрозрачным).

Принимает одно из следующих:

  • строку (часто heredoc)
  • false, что сделает сущность невидимой для инструментов извлечения документации, таких как ExDoc
  • список ключевых слов, начиная с Elixir 1.7.0

Например:

defmodule MyModule do
  @typedoc "This type"
  @typedoc since: "1.1.0"
  @type t :: term

  @doc "Hello world"
  @doc since: "1.1.0"
  def hello do
    "world"
  end

  @doc """
  Sums `a` to `b`.
  """
  def sum(a, b) do
    a + b
  end
end

Как видно из примера выше, начиная с Elixir 1.7.0 @doc и @typedoc также принимают список ключевых слов, который служит способом предоставления произвольных метаданных о сущности. Инструменты, такие как ExDoc и IEx, могут использовать эту информацию для отображения аннотаций. Распространённым случаем использования является ключ :since, который может быть использован для аннотации версии, в которой функция была введена.

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

Обратите внимание, что так как компилятор также определяет некоторые дополнительные метаданные, существуют некоторые зарезервированные ключи, которые будут игнорироваться, и о которых будет выведено предупреждение, если они используются. В настоящее время это: :opaque и :defaults.

После компиляции этого модуля эта информация становится доступной через функцию Code.fetch_docs/1.

@dialyzer

Определяет предупреждения для запроса или подавления при использовании :dialyzer.

Принимает атом, кортеж или список атомов и кортежей. Например:

defmodule MyModule do
  @dialyzer {:nowarn_function, [my_fun: 1]}

  def my_fun(arg) do
    M.not_a_function(arg)
  end
end

Список поддерживаемых предупреждений см. в :dialyzer модуле.

Несколько применений @dialyzer будут накапливаться, а не перезаписывать предыдущие.

@external_resource

Указывает внешний ресурс для текущего модуля.

Иногда модуль встраивает информацию из внешнего файла. Этот атрибут позволяет модулю аннотировать используемые внешние ресурсы.

Инструменты могут использовать эту информацию для обеспечения перекомпиляции модуля в случае изменения каких-либо внешних ресурсов, например: mix compile.elixir.

Указанный путь к файлу интерпретируется как относительный к папке, содержащей mix.exs проекта, то есть текущей рабочей папке, а не к файлу, где @external_resource объявлен.

Если внешний ресурс не существует, модуль всё равно зависит от него, заставляя модуль перекомпилироваться, как только файл будет добавлен.

Для большего контроля над перекомпиляцией модуля см. __mix_recompile__?/0.

@file

Изменяет имя файла, используемое в отслеживании стека для функции или макроса, за которым следует атрибут, например:

defmodule MyModule do
  @doc "Hello world"
  @file "hello.ex"
  def hello do
    "world"
  end
end

Обратите внимание, что это верно только для исключений/диагностических данных, которые исходят из внутреннего области видимости определения (включая шаблоны и защитные конструкции). Например:

defmodule MyModule do # <---- module definition
  @file "hello.ex"
  defp unused(a) do # <---- function definition
    "world" # <---- function scope
  end

  @file "bye.ex"
  def unused(_), do: true
end

Если запустить этот код с прокомментированной второй декларацией «unused», вы увидите, что hello.ex используется в отслеживании стека при сообщении о предупреждениях, но если вы его раскомментируете, вы увидите, что ошибка не будет упоминать bye.ex, потому что это ошибка уровня модуля, а не ошибка выражения.

@moduledoc

Предоставляет документацию для текущего модуля.

defmodule MyModule do
  @moduledoc """
  A very useful module.
  """
  @moduledoc authors: ["Alice", "Bob"]
end

Принимает строку (часто heredoc) или false, где @moduledoc false сделает модуль невидимым для инструментов извлечения документации, таких как ExDoc.

Аналогично @doc также принимает список ключевых слов для предоставления метаданных о модуле. Для получения дополнительной информации см. документацию по @doc выше.

После компиляции этого модуля эта информация становится доступной через функцию Code.fetch_docs/1.

@nifs (с версии v1.16.0)

Список функций и их арностей, которые будут переопределены с помощью родного (NIF) исполнения.

defmodule MyLibrary.MyModule do
  @nifs [foo: 1, bar: 2]

  def foo(arg1), do: :erlang.nif_error(:not_loaded)
  def bar(arg1, arg2), do: :erlang.nif_error(:not_loaded)
end

См. документацию Erlang для получения дополнительной информации: https://www.erlang.org/doc/man/erl_nif

@on_definition

Хук, который будет вызван при определении каждой функции или макроса в текущем модуле. Полезно при аннотации функций.

Принимает модуль или кортеж {module, function_name}. Функция должна принимать 6 аргументов:

  • среду модуля
  • тип функции/макроса: :def, :defp, :defmacro, или :defmacrop
  • имя функции/макроса
  • список цитируемых аргументов
  • список цитируемых защит
  • цитируемое тело функции

Если определяемая функция/макрос имеет несколько разделов, обработчик будет вызываться для каждого раздела.

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

Когда предоставляется только модуль, функция предполагается __on_definition__/6.

Пример

defmodule Hooks do
  def on_def(_env, kind, name, args, guards, body) do
    IO.puts("Defining #{kind} named #{name} with args:")
    IO.inspect(args)
    IO.puts("and guards")
    IO.inspect(guards)
    IO.puts("and body")
    IO.puts(Macro.to_string(body))
  end
end

defmodule MyModule do
  @on_definition {Hooks, :on_def}

  def hello(arg) when is_binary(arg) or is_list(arg) do
    "Hello" <> to_string(arg)
  end

  def hello(_) do
    :ok
  end
end

@on_load

Обработчик, который будет вызываться всякий раз, когда модуль загружается.

Принимает имя функции (как атом) функции в текущем модуле. Функция должна иметь арность 0 (без аргументов). Если функция не возвращает :ok, загрузка модуля будет прервана. Например:

defmodule MyModule do
  @on_load :load_check

  def load_check do
    if some_condition() do
      :ok
    else
      :abort
    end
  end

  def some_condition do
    false
  end
end

@vsn

Укажите версию модуля. Принимает любое допустимое значение Elixir, например:

defmodule MyModule do
  @vsn "1.0"
end

Атрибуты структуры

  • @derive - выводит реализацию для данного протокола для структуры, определенной в текущем модуле

  • @enforce_keys - гарантирует, что указанные ключи всегда устанавливаются при построении структуры, определенной в текущем модуле

См. defstruct/1 для получения дополнительной информации о создании и использовании структур.

Атрибуты типов

Следующие атрибуты являются частью типов и также встроенными в Elixir:

  • @type - определяет тип, который будет использоваться в @spec
  • @typep - определяет частный тип, который будет использоваться в @spec
  • @opaque - определяет непрозрачный тип, который будет использоваться в @spec
  • @spec - предоставляет описание для функции
  • @callback - предоставляет описание для обратного вызова поведения (и генерирует функцию behaviour_info/1 в модуле, см. ниже)
  • @macrocallback - предоставляет описание для обратного вызова макроса поведения
  • @optional_callbacks - определяет, какие обратные вызовы поведения и обратные вызовы макросов поведения являются необязательными
  • @impl - объявляет реализацию функции обратного вызова или макроса

Для получения подробных сведений см. документацию по типам.

Пользовательские атрибуты

В дополнение к встроенным атрибутам, перечисленным выше, можно добавить пользовательские атрибуты. Пользовательские атрибуты выражаются с помощью оператора @/1, за которым следует допустимое имя переменной. Значение, присваиваемое пользовательскому атрибуту, должно быть допустимым значением Elixir:

defmodule MyModule do
  @custom_attr [some: "stuff"]
end

Для получения более расширенных вариантов при определении пользовательских атрибутов, см. register_attribute/3.

Обратные вызовы компиляции

Существует три обратных вызова компиляции, вызываемые в таком порядке: @before_compile, @after_compile, и @after_verify. Они описаны ниже.

@before_compile

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

Принимает модуль или кортеж {module, function_or_macro_name} . Функция/макрос должна принимать один аргумент: среду модуля. Если это макрос, возвращаемое значение будет вставлено в конец определения модуля перед началом компиляции.

Когда предоставляется только модуль, функция/макрос предполагается __before_compile__/1.

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

Примечание: функция/макрос обратного вызова должен быть помещен в отдельный модуль (потому что когда вызывается обратный вызов, текущий модуль еще не существует).

Пример

defmodule A do
  defmacro __before_compile__(_env) do
    quote do
      def hello, do: "world"
    end
  end
end

defmodule B do
  @before_compile A
end

B.hello()
#=> "world"

@after_compile

Обработчик, который будет вызван сразу после компиляции текущего модуля.

Принимает модуль или кортеж {module, function_name} . Функция должна принимать два аргумента: среду модуля и его байт-код. Когда предоставляется только модуль, функция предполагается __after_compile__/2.

Обратные вызовы будут выполняться в порядке их регистрации.

Module функции, ожидающие еще не скомпилированные модули (например, definitions_in/1), все еще доступны в момент вызова @after_compile.

Пример

defmodule MyModule do
  @after_compile __MODULE__

  def __after_compile__(env, _bytecode) do
    IO.inspect(env)
  end
end

@after_verify

Обработчик, который будет вызван сразу после проверки текущего модуля на наличие неопределенных функций, устаревших функций и т. д. Модуль всегда проверяется после компиляции. В проектах Mix модуль также проверяется при изменении любых его зависимостей времени выполнения. Поэтому это полезно для проверки текущего модуля, избегая зависимостей времени компиляции. Учитывая, что обратный вызов вызывается в разных сценариях, Elixir не гарантирует, когда в цикле компиляции или в каком процессе выполняется обратный вызов.

Принимает модуль или кортеж {module, function_name} . Функция должна принимать один аргумент: имя модуля. Когда предоставляется только модуль, функция предполагается __after_verify__/1.

Обратные вызовы будут выполняться в порядке их регистрации.

Module функции, ожидающие еще не скомпилированные модули, больше недоступны в момент вызова @after_verify.

Пример

defmodule MyModule do
  @after_verify __MODULE__

  def __after_verify__(module) do
    IO.inspect(module)
    :ok
  end
end

Опции компиляции

Атрибут @compile принимает разные опции, которые используются как компиляторами Elixir, так и Erlang. Некоторые общие случаи использования описаны ниже:

  • @compile :debug_info - включает :debug_info независимо от соответствующего параметра в Code.get_compiler_option/1

  • @compile {:debug_info, false} - отключает :debug_info независимо от соответствующего параметра в Code.get_compiler_option/1. Отключение :debug_info не рекомендуется, так как оно лишает компилятор Elixir и других инструментов возможности статического анализа кода. Если вы хотите удалить :debug_info при развертывании, такие инструменты, как mix release, уже делают это по умолчанию.

  • @compile {:inline, some_fun: 2, other_fun: 3} - встраивает заданные пары имя/арность. Встраивание применяется локально, вызовы из другого модуля не влияют на эту опцию

  • @compile {:autoload, false} - отключает автоматическую загрузку модулей после компиляции. Вместо этого модуль будет загружен после отправки его

  • @compile {:no_warn_undefined, Mod} или @compile {:no_warn_undefined, {Mod, fun, arity}} - не предупреждает, если заданный модуль или заданный Mod.fun/arity не определены

Сгенерированные функции

Иногда компилятор генерирует публичные функции внутри модулей. Они документированы ниже.

behaviour_info/1

Эта функция генерируется для модулей, которые определяют поведение, то есть которые имеют одно или несколько определений @callback. Подпись этой функции, выраженная как спецификация, имеет вид:

@spec behaviour_info(:callbacks) :: [function_info]
  when function_info: {function_name :: atom(), arity :: non_neg_integer()}

@spec behaviour_info(:optional_callbacks) :: [function_info]
  when function_info: {function_name :: atom(), arity :: non_neg_integer()}

behaviour_info(:callbacks) включает необязательные обратные вызовы.

Например:

iex> Enum.sort(GenServer.behaviour_info(:callbacks))
[
  code_change: 3,
  format_status: 1,
  format_status: 2,
  handle_call: 3,
  handle_cast: 2,
  handle_continue: 2,
  handle_info: 2,
  init: 1,
  terminate: 2
]

module_info/0

Эта функция генерируется для всех модулей. Она возвращает все атрибуты, возвращаемые module_info/1 (см. ниже), но в виде одного списка ключевых слов. См. также документацию Erlang.

module_info/1

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

@spec module_info(:module) :: module() # Returns the module itself
@spec module_info(:attributes) :: keyword()
@spec module_info(:compile) :: keyword()
@spec module_info(:md5) :: binary()
@spec module_info(:nifs) :: module()
@spec module_info(:exports) :: [function_info]
  when function_info: {function_name :: atom(), arity :: non_neg_integer()}
@spec module_info(:functions) :: [function_info]
  when function_info: {function_name :: atom(), arity :: non_neg_integer()}

Например:

iex> URI.module_info(:module)
URI
iex> {:decode_www_form, 1} in URI.module_info(:exports)
true

Для получения дополнительной информации о module_info/1, также ознакомьтесь с документацией Erlang.

__info__/1

Эта функция генерируется для всех модулей. Она похожа на module_info/1 , но включает некоторую дополнительную информацию, специфичную для Elixir, такую как информация о структуре и макросах. Для получения документации см. Module.__info__/1.

Краткое описание

Типы

def_kind()
definition()

Обработчики событий

__info__(atom)

Предоставляет информацию о функциях, макросах и другой информации, определённой модулем во время выполнения.

Функции

attributes_in(module)

Возвращает все имена атрибутов модуля, определённые в module.

concat(list)

Конкатенирует список псевдонимов и возвращает новый псевдоним.

concat(left, right)

Конкатенирует два псевдонима и возвращает новый псевдоним.

create(module, quoted, opts)

Создаёт модуль с заданным именем, определяемый заданными выражениями с использованием кавычек.

defines?(module, tuple)

Проверяет, определяет ли модуль данную функцию или макрос.

defines?(module, tuple, def_kind)

Проверяет, определяет ли модуль функцию или макрос заданного kind.

defines_type?(module, definition)

Проверяет, определяет ли текущий модуль данный тип (приватный, неявный или нет).

definitions_in(module)

Возвращает все функции и макросы, определённые в module.

definitions_in(module, kind)

Возвращает все функции, определённые в module, в соответствии с их типом.

delete_attribute(module, key)

Удаляет запись (или записи) для данного атрибута модуля.

delete_definition(module, arg)

Удаляет определение из модуля.

eval_quoted(module_or_env, quoted, binding \\ [], opts \\ []) устаревшее
get_attribute(module, key, default \\ nil)

Получает заданный атрибут из модуля.

get_definition(module, arg, options \\ [])

Возвращает определение для заданной пары имя-арность.

get_last_attribute(module, key, default \\ nil)

Возвращает последнее установленное значение заданного атрибута из модуля.

has_attribute?(module, key)

Проверяет, был ли определён заданный атрибут.

make_overridable(module, tuples)

Делает заданные функции в module переопределяемыми.

open?(module)

Проверяет, открыт ли модуль.

overridable?(module, tuple)

Возвращает true, если tuple в module был помечен как переопределяемый на каком-то этапе.

overridables_in(module)

Возвращает все переопределяемые определения в module.

put_attribute(module, key, value)

Устанавливает атрибут модуля с key и value в заданном module.

register_attribute(module, attribute, options)

Регистрирует атрибут.

reserved_attributes()

Возвращает информацию об атрибутах модуля, используемых Elixir.

safe_concat(list)

Конкатенирует список псевдонимов и возвращает новый псевдоним только в том случае, если псевдоним уже был использован.

safe_concat(left, right)

Конкатенирует два псевдонима и возвращает новый псевдоним только в том случае, если псевдоним уже был использован.

spec_to_callback(module, definition)

Копирует заданный шаблон в качестве обратного вызова.

split(module)

Разделяет имя заданного модуля на бинарные части.

Типы

def_kind()Source

@type def_kind() :: :def | :defp | :defmacro | :defmacrop

definition()Source

@type definition() :: {atom(), arity()}

Обработчики событий

__info__(atom)Source

@callback __info__(:attributes) :: keyword()
@callback __info__(:compile) :: [term()]
@callback __info__(:functions) :: keyword()
@callback __info__(:macros) :: keyword()
@callback __info__(:md5) :: binary()
@callback __info__(:module) :: module()
@callback __info__(:struct) :: [%{:field => atom(), optional(:default) => term()}] | nil

Предоставляет информацию о функциях, макросах и другой информации, определённой модулем во время выполнения.

Каждый модуль получает функцию __info__/1, когда он компилируется. Функция принимает один из следующих элементов:

  • :attributes - список ключевых слов со всеми сохранёнными атрибутами

  • :compile - список метаданных компилятора

  • :functions - список ключевых слов с общедоступными функциями и их арностями

  • :macros - список ключевых слов с общедоступными макросами и их арностями

  • :md5 - MD5 модуля

  • :module - атомное имя модуля

  • :struct - (с версии 1.14.0) если модуль определяет структуру, то каждый элемент в порядке следования.

Функции

attributes_in(модуль)Исходный код

@spec attributes_in(module()) :: [atom()]

Возвращает все имена атрибутов модуля, определённые в module.

Эта функция может быть использована только для модулей, которые ещё не были скомпилированы.

Примеры

defmodule Example do
  @foo 1
  Module.register_attribute(__MODULE__, :bar, accumulate: true)

  :foo in Module.attributes_in(__MODULE__)
  #=> true

  :bar in Module.attributes_in(__MODULE__)
  #=> true
end

concat(список)Исходный код

@spec concat([binary() | atom()]) :: atom()

Конкатенирует список псевдонимов и возвращает новый псевдоним.

Обрабатывает бинарные данные и атомы.

Примеры

iex> Module.concat([Foo, Bar])
Foo.Bar

iex> Module.concat([Foo, "Bar"])
Foo.Bar

concat(левый, правый)Исходный код

@spec concat(binary() | atom(), binary() | atom()) :: atom()

Конкатенирует два псевдонима и возвращает новый псевдоним.

Обрабатывает бинарные данные и атомы.

Примеры

iex> Module.concat(Foo, Bar)
Foo.Bar

iex> Module.concat(Foo, "Bar")
Foo.Bar

create(модуль, с цитатами, параметры)Исходный код

@spec create(module(), Macro.t(), Macro.Env.t() | keyword()) ::
  {:module, module(), binary(), term()}

Создаёт модуль с заданным именем и определённый с помощью данных выражений с цитатами.

Строка, где модуль определён, и его файл обязательно должны быть переданы в качестве параметров. Смотрите Code.env_for_eval/1 для полного списка параметров.

Возвращает кортеж вида {:module, module, binary, term}, где module - имя модуля, binary - байткод модуля и term - результат последнего выражения в quoted.

Аналогично Kernel.defmodule/2, бинарный файл будет записан на диск только как .beam файл, если Module.create/3 вызывается в файле, который в данный момент компилируется.

Примеры

contents =
  quote do
    def world, do: true
  end

Module.create(Hello, contents, Macro.Env.location(__ENV__))

Hello.world()
#=> true

Отличия от defmodule

Module.create/3 работает аналогично Kernel.defmodule/2 и возвращает те же результаты. Хотя можно использовать Kernel.defmodule/2 для динамического определения модулей, эта функция предпочтительнее, когда тело модуля задано выражением с цитатами.

Ещё одно важное отличие заключается в том, что Module.create/3 позволяет контролировать переменные среды, используемые при определении модуля, в то время как Kernel.defmodule/2 автоматически использует среду, в которой она вызывается.

defines?(модуль, кортеж)Исходный код

@spec defines?(module(), definition()) :: boolean()

Проверяет, определяет ли модуль данную функцию или макрос.

Используйте defines?/3 для проверки конкретного типа.

Эта функция может быть использована только для модулей, которые ещё не были скомпилированы. Используйте Kernel.function_exported?/3 и Kernel.macro_exported?/3 для проверки публичных функций и макросов соответственно в скомпилированных модулях.

Обратите внимание, что defines? возвращает false для функций и макросов, которые были определены, но затем помечены как переопределяемые, и никакой другой реализации не было предоставлено. Вы можете проверить статус переопределяемости, вызвав overridable?/2.

Примеры

defmodule Example do
  Module.defines?(__MODULE__, {:version, 0}) #=> false
  def version, do: 1
  Module.defines?(__MODULE__, {:version, 0}) #=> true
end

defines?(модуль, кортеж, тип_определения)Исходный код

@spec defines?(module(), definition(), def_kind()) :: boolean()

Проверяет, определяет ли модуль функцию или макрос заданного kind.

kind может быть любым из :def, :defp, :defmacro, или :defmacrop.

Эта функция может быть использована только для модулей, которые ещё не были скомпилированы. Используйте Kernel.function_exported?/3 и Kernel.macro_exported?/3 для проверки публичных функций и макросов соответственно в скомпилированных модулях.

Примеры

defmodule Example do
  Module.defines?(__MODULE__, {:version, 0}, :def) #=> false
  def version, do: 1
  Module.defines?(__MODULE__, {:version, 0}, :def) #=> true
end

defines_type?(модуль, определение)Исходный код

@spec defines_type?(module(), definition()) :: boolean()

Проверяет, определяет ли текущий модуль данный тип (приватный, непрозрачный или нет).

Эта функция доступна только для компилируемых модулей.

definitions_in(модуль)Исходный код

@spec definitions_in(module()) :: [definition()]

Возвращает все функции и макросы, определённые в module.

Возвращает список всех определённых функций и макросов, публичных и приватных, в форме [{name, arity}, ...].

Эта функция может быть использована только для модулей, которые ещё не были скомпилированы. Используйте обратный вызов Module.__info__/1 для получения публичных функций и макросов в скомпилированных модулях.

Примеры

defmodule Example do
  def version, do: 1
  defmacrop test(arg), do: arg
  Module.definitions_in(__MODULE__) #=> [{:version, 0}, {:test, 1}]
end

definitions_in(модуль, тип)Исходный код

@spec definitions_in(module(), def_kind()) :: [definition()]

Возвращает все функции, определённые в module, согласно его типу.

Эта функция может быть использована только для модулей, которые ещё не были скомпилированы. Используйте обратный вызов Module.__info__/1 для получения публичных функций и макросов в скомпилированных модулях.

Примеры

defmodule Example do
  def version, do: 1
  Module.definitions_in(__MODULE__, :def)  #=> [{:version, 0}]
  Module.definitions_in(__MODULE__, :defp) #=> []
end

delete_attribute(модуль, ключ)Исходный код

@spec delete_attribute(module(), atom()) :: term()

Удаляет запись (или записи) для данного атрибута модуля.

Возвращает удалённое значение атрибута. Если атрибут не был установлен и не был сконфигурирован для накопления, возвращает nil.

Если атрибут настроен на накопление, то эта функция всегда возвращает список. Удаление атрибута удаляет существующие записи, но атрибут всё ещё будет накапливать.

Примеры

defmodule MyModule do
  Module.put_attribute(__MODULE__, :custom_threshold_for_lib, 10)
  Module.delete_attribute(__MODULE__, :custom_threshold_for_lib)
end

delete_definition(модуль, аргумент)Исходный код

@spec delete_definition(module(), definition()) :: boolean()

Удаляет определение из модуля.

Возвращает true если определение существует и было удалено, в противном случае возвращает false.

eval_quoted(модуль_или_среда, с цитатами, область_видимости \\ [], параметры \\ [])Исходный код

Эта функция устарела. Используйте Code.eval_quoted/3 вместо неё.

get_attribute(модуль, ключ, значение_по_умолчанию \\ null)Исходный код

@spec get_attribute(module(), atom(), term()) :: term()

Получает указанный атрибут из модуля.

Если атрибут был помечен accumulate с помощью Module.register_attribute/3, всегда возвращается список. nil возвращается, если атрибут не был помечен accumulate и не был установлен ни на какое значение.

Макрос @ компилируется в вызов этой функции. Например, следующий код:

@foo

Расширяется на что-то вроде:

Module.get_attribute(__MODULE__, :foo)

Эта функция может быть использована только для модулей, которые ещё не были скомпилированы. Используйте обратный вызов Module.__info__/1 для получения всех сохранённых атрибутов или Code.fetch_docs/1 для извлечения всех атрибутов документации в скомпилированных модулях.

Примеры

defmodule Foo do
  Module.put_attribute(__MODULE__, :value, 1)
  Module.get_attribute(__MODULE__, :value) #=> 1

  Module.get_attribute(__MODULE__, :value, :default) #=> 1
  Module.get_attribute(__MODULE__, :not_found, :default) #=> :default

  Module.register_attribute(__MODULE__, :value, accumulate: true)
  Module.put_attribute(__MODULE__, :value, 1)
  Module.get_attribute(__MODULE__, :value) #=> [1]
end
END_OF_DOCUMENT_MARKER

get_definition(module, arg, options \\ [])Source

@spec get_definition(module(), definition(), keyword()) ::
  {:v1, def_kind(), meta :: keyword(),
   [
     {meta :: keyword(), arguments :: [Macro.t()], guards :: [Macro.t()],
      Macro.t()}
   ]}
  | nil

Возвращает определение для заданной пары имя-арность.

Возвращает кортеж с version, kind, определением metadata, и списком с каждой из клауз. Каждая клауза — кортеж из четырёх элементов: метаданные, аргументы, условия и AST клаузы.

Клаузы возвращаются в формате Elixir AST, но уже расширенные и нормализованные. Это полезно для анализа кода, но их нельзя повторно вставить в модуль, так как они потеряют часть своего контекста. Поскольку это представление AST в основном внутреннее, оно имеет версионирование и может меняться в любое время. Поэтому используйте этот API с осторожностью.

Параметры

  • :skip_clauses (с версии v1.14.0) — возвращает [] вместо возврата клауз. Это полезно, когда интересуют только тип и метаданные.

get_last_attribute(module, key, default \\ nil)Source

@spec get_last_attribute(module(), atom(), term()) :: term()

Получает последнее установленное значение атрибута из модуля.

Если атрибут помечен как accumulate с Module.register_attribute/3, будет возвращено предыдущее установленное значение. Если атрибут не накапливает значения, этот вызов эквивалентен вызову Module.get_attribute/3.

Данная функция может быть использована только с модулями, которые ещё не скомпилированы. Используйте обратный вызов Module.__info__/1 для получения всех сохранённых атрибутов или Code.fetch_docs/1 для получения всех атрибутов документации в скомпилированных модулях.

Примеры

defmodule Foo do
  Module.put_attribute(__MODULE__, :value, 1)
  Module.get_last_attribute(__MODULE__, :value) #=> 1

  Module.get_last_attribute(__MODULE__, :not_found, :default) #=> :default

  Module.register_attribute(__MODULE__, :acc, accumulate: true)
  Module.put_attribute(__MODULE__, :acc, 1)
  Module.get_last_attribute(__MODULE__, :acc) #=> 1
  Module.put_attribute(__MODULE__, :acc, 2)
  Module.get_last_attribute(__MODULE__, :acc) #=> 2
end

has_attribute?(module, key)Source

@spec has_attribute?(module(), atom()) :: boolean()

Проверяет, определён ли заданный атрибут.

Атрибут считается определённым, если он был зарегистрирован с помощью register_attribute/3 или ему было присвоено значение. Если атрибут был удалён с помощью delete_attribute/2, он больше не считается определённым.

Эта функция может быть использована только с модулями, которые ещё не скомпилированы.

Примеры

defmodule MyModule do
  @value 1
  Module.register_attribute(__MODULE__, :other_value)
  Module.put_attribute(__MODULE__, :another_value, 1)

  Module.has_attribute?(__MODULE__, :value) #=> true
  Module.has_attribute?(__MODULE__, :other_value) #=> true
  Module.has_attribute?(__MODULE__, :another_value) #=> true

  Module.has_attribute?(__MODULE__, :undefined) #=> false

  Module.delete_attribute(__MODULE__, :value)
  Module.has_attribute?(__MODULE__, :value) #=> false
end

make_overridable(module, tuples)Source

@spec make_overridable(module(), [definition()]) :: :ok
@spec make_overridable(module(), module()) :: :ok

Делает заданные функции в module переопределяемыми.

Переопределяемая функция определяется лениво, что позволяет разработчику её настраивать. Подробнее см. Kernel.defoverridable/1.

После того, как функция или макрос помечены как переопределяемые, они больше не будут отображаться в definitions_in/1 или возвращать true при передаче в defines?/2, пока не будет предоставлена другая реализация.

open?(module)Source

@spec open?(module()) :: boolean()

Проверяет, открыт ли модуль.

Модуль «открыт», если он в настоящее время определяется и его атрибуты и функции могут быть изменены.

overridable?(module, tuple)Source

@spec overridable?(module(), definition()) :: boolean()

Возвращает true, если tuple в module был помечен как переопределяемый в какой-то момент.

Обратите внимание, что overridable?/2 возвращает true даже если определение уже переопределено. Вы можете использовать defines?/2, чтобы узнать, существует ли определение или оно ожидается.

overridables_in(module)Source

@spec overridables_in(module()) :: [atom()]

Возвращает все переопределяемые определения в module.

Обратите внимание, что определение включается даже если оно уже переопределено. Вы можете использовать defines?/2, чтобы узнать, существует ли определение или оно ожидается.

Эта функция может быть использована только с модулями, которые ещё не скомпилированы.

Примеры

defmodule Example do
  def foo, do: 1
  def bar, do: 2

  defoverridable foo: 0, bar: 0
  def foo, do: 3

  [bar: 0, foo: 0] = Module.overridables_in(__MODULE__) |> Enum.sort()
end

put_attribute(module, key, value)Source

@spec put_attribute(module(), atom(), term()) :: :ok

Устанавливает атрибут модуля с key и value в заданном module.

Примеры

defmodule MyModule do
  Module.put_attribute(__MODULE__, :custom_threshold_for_lib, 10)
end

register_attribute(module, attribute, options)Source

@spec register_attribute(module(), atom(), accumulate: boolean(), persist: boolean()) ::
  :ok

Регистрирует атрибут.

Регистрация атрибута позволяет настроить, как Elixir будет хранить и накапливать значения атрибутов.

Параметры

При регистрации атрибута можно задать два параметра:

  • :accumulate — несколько вызовов одного и того же атрибута будут накапливаться, а не переопределять предыдущее значение. Новые атрибуты всегда добавляются в начало накопительного списка.

  • :persist — атрибут будет сохранён в формате Erlang Abstract Format. Полезно при взаимодействии с библиотеками Erlang.

По умолчанию оба параметра false. После того, как атрибут установлен для накопления или сохранения, его поведение нельзя изменить.

Примеры

defmodule MyModule do
  Module.register_attribute(__MODULE__, :custom_threshold_for_lib, accumulate: true)

  @custom_threshold_for_lib 10
  @custom_threshold_for_lib 20
  @custom_threshold_for_lib #=> [20, 10]
end

reserved_attributes()Source

@spec reserved_attributes() :: map()

Возвращает информацию об атрибутах модуля, используемых Elixir.

Дополнительную информацию об каждом атрибуте см. в разделе «Атрибуты модуля» в документации модуля.

Примеры

iex> map = Module.reserved_attributes()
iex> Map.has_key?(map, :moduledoc)
true
iex> Map.has_key?(map, :doc)
true

safe_concat(list)Source

@spec safe_concat([binary() | atom()]) :: atom()

Конкатенирует список псевдонимов и возвращает новый псевдоним только если он уже ссылается.

Если псевдоним ещё не был использован, возникает ошибка ArgumentError. Обрабатывает бинарные и атомы.

Примеры

iex> Module.safe_concat([List, Chars])
List.Chars

safe_concat(left, right)Source

@spec safe_concat(binary() | atom(), binary() | atom()) :: atom()

Конкатенирует два псевдонима и возвращает новый псевдоним только если он уже ссылается.

Если псевдоним ещё не был использован, возникает ошибка ArgumentError. Обрабатывает бинарные и атомы.

Примеры

iex> Module.safe_concat(List, Chars)
List.Chars

spec_to_callback(module, definition)Source

@spec spec_to_callback(module(), definition()) :: boolean()

Копирует заданный спецификатор как обратный вызов.

Возвращает true если такой спецификатор существует и был скопирован как обратный вызов. Если у функции, связанной со спецификатором, определена документация до вызова этой функции, документация также копируется.

split(module)Source

@spec split(module() | String.t()) :: [String.t(), ...]

Разделяет заданное имя модуля на бинарные части.

module должен быть модулем Elixir, так как split/1 не будет работать с модулями в стиле Erlang (например, split(:lists) вызывает ошибку).

split/1 также поддерживает разделение строкового представления модулей Elixir (то есть результат вызова Atom.to_string/1 с именем модуля).

Примеры

iex> Module.split(Very.Long.Module.Name.And.Even.Longer)
["Very", "Long", "Module", "Name", "And", "Even", "Longer"]
iex> Module.split("Elixir.String.Chars")
["String", "Chars"]

Скачать версию ePub

Создано с помощью ExDoc (v0.36.1) для языка программирования Elixir

© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.18.1/Module.html

Spec-Zone.ru

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