Spec-Zone.ru › Elixir 1.10

Модуль behaviour

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

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

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

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

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

@after_compile

Обработчик, который будет вызван сразу после компиляции текущего модуля. Принимает модуль или {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

Для облегчения правильной реализации поведения, вы можете (по желанию) объявить @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

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

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, где @doc false сделает сущность невидимой для инструментов извлечения документации, таких как ExDoc. Например:

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

Как видно из примера, @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, могут использовать эту информацию, чтобы гарантировать, что модуль будет перекомпилирован в случае изменения какого-либо внешнего ресурса.

@file

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

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

@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.

@on_definition

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

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

@on_load

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

Принимает имя функции (как атом) функции в текущем модуле или {function_name, 0} кортеж, где function_name — имя функции в текущем модуле. Функция должна быть публичной и иметь арность 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

Модули, скомпилированные с HiPE, не будут вызывать этот обработчик.

@vsn

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

defmodule MyModule do
  @vsn "1.0"
end

Атрибуты типов спецификаций

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

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

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

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

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

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

Обработчики компиляции

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

@after_compile

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

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

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

Пример

defmodule MyModule do
  @after_compile __MODULE__

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

@before_compile

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

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

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

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

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

Пример

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"

@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

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

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

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

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

  • @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 не определены

Вы можете увидеть еще несколько опций, используемых компилятором Erlang, в документации для :compile модуля.

Сводка

Функции

concat(список)

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

concat(левый, правый)

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

create(модуль, кавычки, opts)

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

defines?(модуль, кортеж)

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

defines?(модуль, кортеж, def_kind)

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

defines_type?(модуль, определение)

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

definitions_in(модуль)

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

definitions_in(модуль, def_kind)

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

delete_attribute(модуль, ключ)

Удаляет атрибут модуля, соответствующий заданному ключу.

eval_quoted(модуль_или_среда, кавычки, binding \\ [], opts \\ [])

Вычисляет содержимое в кавычках в контексте данного модуля.

get_attribute(модуль, ключ, значение_по_умолчанию \\ nil)

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

has_attribute?(модуль, ключ)

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

make_overridable(модуль, кортежи)

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

open?(модуль)

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

overridable?(модуль, кортеж)

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

put_attribute(модуль, ключ, значение)

Добавляет атрибут модуля с key и value в данный module.

register_attribute(модуль, атрибут, опции)

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

safe_concat(список)

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

safe_concat(левый, правый)

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

spec_to_callback(модуль, определение)

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

split(модуль)

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

Обратные вызовы

__info__(атом)

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

END_OF_DOCUMENT_MARKER ```

Функции

concat(list)

Спецификации

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

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

Примеры

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

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

concat(left, right)

Спецификации

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

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

Примеры

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

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

create(module, quoted, opts)

Спецификации

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

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

Строка, где определён модуль, и его файл должны быть переданы как опции.

Возвращает кортеж формы {: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 и возвращает те же результаты. Хотя можно также использовать defmodule для динамического определения модулей, эта функция предпочтительнее, когда тело модуля задано скобочным выражением.

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

defines?(module, tuple)

Спецификации

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?(module, tuple, def_kind)

Спецификации

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?(module, definition)

Спецификации

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

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

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

definitions_in(module)

Спецификации

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(module, def_kind)

Спецификации

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(module, key)

Спецификации

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

eval_quoted(module_or_env, quoted, binding \\ [], opts \\ [])

Спецификации

eval_quoted(
  module() | Macro.Env.t(),
  Macro.t(),
  list(),
  keyword() | Macro.Env.t()
) :: term()

Вычисляет скобочные содержимое в контексте данного модуля.

Список опций окружения также может быть передан в качестве аргумента. См. Code.eval_string/3 для получения дополнительной информации.

Вызывает ошибку, если модуль уже был скомпилирован.

Примеры

defmodule Foo do
  contents =
    quote do
      def sum(a, b), do: a + b
    end

  Module.eval_quoted(__MODULE__, contents)
end

Foo.sum(1, 2)
#=> 3

Для удобства вы можете передать любую структуру Macro.Env, такую как __ENV__/0, в качестве первого аргумента или как опции. И модуль, и все опции будут автоматически извлечены из среды:

defmodule Foo do
  contents =
    quote do
      def sum(a, b), do: a + b
    end

  Module.eval_quoted(__ENV__, contents)
end

Foo.sum(1, 2)
#=> 3

Обратите внимание, что если вы передаёте структуру Macro.Env в качестве первого аргумента, а также передаёте opts, они будут объединены, opts будет иметь приоритет.

get_attribute(module, key, default \\ nil)

Спецификации

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

has_attribute?(module, key)

Спецификации

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)

Спецификации

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

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

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

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

open?(module)

Спецификации

open?(module()) :: boolean()

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

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

overridable?(module, tuple)

Спецификации

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

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

put_attribute(module, key, value)

Спецификации

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)

Спецификации

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

safe_concat(list)

Спецификации

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

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

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

Примеры

iex> Module.safe_concat([Module, Unknown])
** (ArgumentError) argument error

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

safe_concat(left, right)

Спецификации

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

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

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

Примеры

iex> Module.safe_concat(Module, Unknown)
** (ArgumentError) argument error

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

spec_to_callback(module, definition)

Спецификации

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

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

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

split(module)

Спецификации

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"]

Обратные вызовы

__info__(atom)

Спецификации

__info__(:attributes) :: keyword()
__info__(:compile) :: [term()]
__info__(:functions) :: keyword()
__info__(:macros) :: keyword()
__info__(:md5) :: binary()
__info__(:module) :: module()

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

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

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

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

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

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

  • :md5 - MD5 хэш модуля

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

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.10.4/Module.html

Spec-Zone.ru

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