Spec-Zone.ru › Elixir 1.14

Код

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

Этот модуль дополняет модуль Erlang's :code, добавляя поведение, специфичное для Elixir. Для функций манипулирования AST Elixir (а не его оценки), см. модуль Macro.

Работа с файлами

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

  • require_file/2 - компилирует файл и отслеживает его имя. Он не компилирует файл повторно, если он уже был потребован ранее.

  • compile_file/2 - компилирует файл без отслеживания его имени. Компилирует файл несколько раз при многократном вызове.

  • eval_file/2 - оценивает содержимое файла без отслеживания его имени. Он возвращает результат последнего выражения в файле, а не определенных в нем модулей. Оцениваемые файлы не запускают отслеживания компиляции, описанные в следующем разделе.

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

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

Вышеуказанные функции работают с исходным кодом Elixir. Если вы хотите работать с модулями, скомпилированными в байткод, имеющими расширение .beam и обычно расположенными ниже каталога _build проекта Mix, см. функции в модуле Erlang's :code.

Загрузка кода в Erlang VM

Erlang имеет два режима загрузки кода: интерактивный и встроенный.

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

Вы можете использовать ensure_loaded/1 (а также ensure_loaded?/1 и ensure_loaded!/1), чтобы проверить, загружен ли модуль перед его использованием и принять соответствующие действия.

ensure_compiled/1 и ensure_compiled!/1

Elixir также включает функции ensure_compiled/1 и ensure_compiled!/1, которые являются надмножеством ensure_loaded/1.

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

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

Если вы используете Code.ensure_compiled/1, вы предполагаете, что можете продолжить без модуля, и поэтому Elixir может вернуть {:error, :unavailable} в случаях, когда модуль еще недоступен (но может стать доступным позже).

По этим причинам разработчики обычно используют Code.ensure_compiled!/1. В частности, не делайте следующее:

case Code.ensure_compiled(module) do
  {:module, _} -> module
  {:error, _} -> raise ...
end

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

В большинстве случаев ensure_loaded/1 достаточно. ensure_compiled!/1 необходимо использовать в редких случаях, обычно связанных с макросами, которые должны вызывать модуль для получения информации о обратных вызовах. Использование ensure_compiled/1 еще менее вероятно.

Отслеживатели компиляции

Elixir поддерживает отслеживатели компиляции, которые позволяют модулям наблюдать за конструкциями, обрабатываемыми компилятором Elixir при компиляции файлов. Отслеживатель — это модуль, реализующий функцию trace/2. Функция получает имя события в качестве первого аргумента и Macro.Env в качестве второго и должна вернуть :ok. Очень важно, чтобы отслеживатель выполнял как можно меньше работы синхронно и передавал основную часть работы в отдельный процесс. Медленные отслеживатели замедлят компиляцию.

Вы можете настроить список отслеживателей с помощью put_compiler_option/2. Следующие события доступны для отслеживателей:

  • :start - (с версии v1.11.0) вызывается всякий раз, когда компилятор начинает отслеживать новый лексический контекст, например, новый файл. Имейте в виду, что компилятор работает параллельно, поэтому несколько файлов могут вызывать :start и выполняться одновременно. Значение lexical_tracker среды макроса, хотя и неявное, может использоваться для уникальной идентификации среды.

  • :stop - (с версии v1.11.0) вызывается всякий раз, когда компилятор прекращает отслеживание нового лексического контекста, например, нового файла.

  • {:import, meta, module, opts} - отслеживается всякий раз, когда module импортируется. meta — это метаданные импорта AST, а opts — это параметры импорта.

  • {:imported_function, meta, module, name, arity} и {:imported_macro, meta, module, name, arity} - отслеживаются всякий раз, когда вызывается импортированная функция или макрос. meta — это метаданные вызова AST, module — это модуль, из которого выполняется импорт, а затем name и arity импортированной функции/макроса.

  • {:alias, meta, alias, as, opts} - отслеживается всякий раз, когда alias алиасируется с as. meta — это метаданные алиаса AST, а opts — это параметры алиаса.

  • {:alias_expansion, meta, as, alias} отслеживается всякий раз, когда происходит расширение алиаса для ранее определенного alias, т.е. когда пользователь вводит as, которое расширяется до alias. meta — это метаданные расширения алиаса AST.

  • {:alias_reference, meta, module} - отслеживается всякий раз, когда в коде есть алиас, т.е. всякий раз, когда пользователь вводит MyModule.Foo.Bar в коде, независимо от того, расширялся он или нет.

  • {:require, meta, module, opts} - отслеживается всякий раз, когда module требуется. meta — это метаданные требования AST, а opts — это параметры требования. Если параметр meta содержит :from_macro, значит, require был вызван изнутри макроса и поэтому должен рассматриваться как зависимость времени компиляции.

  • {:struct_expansion, meta, module, keys} - отслеживается всякий раз, когда структура module расширяется. meta — это метаданные структуры AST, а keys — это ключи, используемые для расширения.

  • {:remote_function, meta, module, name, arity} и {:remote_macro, meta, module, name, arity} - отслеживаются всякий раз, когда ссылаются на удаленную функцию или макрос. meta — это метаданные вызова AST, module — вызываемый модуль, за которым следуют name и arity.

  • {:local_function, meta, name, arity} и {:local_macro, meta, name, arity} - отслеживаются всякий раз, когда ссылаются на локальную функцию или макрос. meta — это метаданные вызова AST, за которым следуют name и arity.

  • {:compile_env, app, path, return} - отслеживается всякий раз, когда вызываются Application.compile_env/3 или Application.compile_env!/2. app — атом, path — список ключей для обхода в среде приложения, а return — это либо {:ok, value}, либо :error.

  • {:on_module, bytecode, _ignore} - (с версии v1.11.0) отслеживается всякий раз, когда определяется модуль. Это эквивалентно обратной функции @after_compile, и вызывается после любого @after_compile в данном модуле. Третий элемент в настоящее время :none, но в будущем он может предоставлять больше метаданных. На данный момент лучше его игнорировать. Обратите внимание, что функции Module, ожидающие еще не скомпилированные модули (такие как Module.definitions_in/1), по-прежнему доступны в момент выдачи этого события.

Параметр компилятора :tracers может быть объединен с параметром компилятора :parser_options для обогащения метаданных отслеживаемых событий выше.

Новые события могут быть добавлены в любое время в будущем, поэтому рекомендуется, чтобы функция trace/2 имела клаузу "catch-all".

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

defmodule MyTracer do
  def trace({:remote_function, _meta, module, name, arity}, env) do
    IO.puts "#{env.file}:#{env.line} #{inspect(module)}.#{name}/#{arity}"
    :ok
  end

  def trace(_event, _env) do
    :ok
  end
end

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

Типы

binding()

Список всех связываний переменных.

Функции

append_path(path)

Добавляет путь в конец списка путей кода Erlang VM.

available_compiler_options()

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

can_await_module_compilation?()

Возвращает true, если текущий процесс может ожидать компиляцию модуля.

compile_file(file, relative_to \\ nil)

Компилирует указанный файл.

compile_quoted(quoted, file \\ "nofile")

Компилирует выражение в виде строки.

compile_string(string, file \\ "nofile")

Компилирует заданную строку.

compiler_options()

Получает все параметры компиляции из сервера кода.

compiler_options(opts)

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

delete_path(path)

Удаляет путь из списка путей кода Erlang VM.

ensure_compiled(module)

Аналогично ensure_compiled!/1, но указывает, что вы можете продолжить без указанного модуля.

ensure_compiled!(module)

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

ensure_loaded(module)

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

ensure_loaded!(module)

То же, что и ensure_loaded/1, но генерирует исключение, если модуль не может быть загружен.

ensure_loaded?(module)

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

env_for_eval(env_or_opts)

Возвращает среду для вычисления.

eval_file(file, relative_to \\ nil)

Вычисляет указанный файл.

eval_quoted(quoted, binding \\ [], env_or_opts \\ [])

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

eval_quoted_with_env(quoted, binding, env)

Вычисляет указанное содержимое quoted со binding и env.

eval_string(string, binding \\ [], opts \\ [])

Вычисляет содержимое, заданное string.

fetch_docs(module_or_path)

Возвращает документацию для указанного модуля или пути к файлу .beam.

format_file!(file, opts \\ [])

Форматирует файл.

format_string!(string, opts \\ [])

Форматирует заданный код string.

get_compiler_option(key)

Возвращает значение заданного параметра компиляции.

prepend_path(path)

Добавляет путь в начало списка путей кода Erlang VM.

purge_compiler_modules()

Очистка модулей компилятора.

put_compiler_option(key, value)

Сохраняет параметр компиляции.

quoted_to_algebra(quoted, opts \\ [])

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

require_file(file, relative_to \\ nil)

Требует указанный file.

required_files()

Список всех требуемых файлов.

string_to_quoted(string, opts \\ [])

Преобразует заданную строку в её строковое представление.

string_to_quoted!(string, opts \\ [])

Преобразует заданную строку в её строковое представление.

string_to_quoted_with_comments(string, opts \\ [])

Преобразует заданную строку в её строковое представление и список комментариев.

string_to_quoted_with_comments!(string, opts \\ [])

Преобразует заданную строку в её строковое представление и список комментариев.

unrequire_files(files)

Удаляет файлы из списка требуемых файлов.

Типы

binding()Source

@type binding() :: [{atom() | tuple(), any()}]

Список всех связываний переменных.

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

Функции

append_path(path)Source

@spec append_path(Path.t()) :: true | {:error, :bad_directory}

Добавляет путь в конец списка путей к коду виртуальной машины Erlang.

Это список каталогов, используемых виртуальной машиной Erlang для поиска модульного кода. Список файлов управляется для каждого узла виртуальной машины Erlang.

Путь расширяется с помощью Path.expand/1 перед добавлением. Если этого пути не существует, возвращается ошибка.

Примеры

Code.append_path(".")
#=> true

Code.append_path("/does_not_exist")
#=> {:error, :bad_directory}

available_compiler_options()Source

@spec available_compiler_options() :: [atom()]

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

Описание всех опций см. в put_compiler_option/2.

Примеры

Code.available_compiler_options()
#=> [:docs, :debug_info, ...]

can_await_module_compilation?()Source

@spec can_await_module_compilation?() :: boolean()

Возвращает true, если текущий процесс может ожидать компиляции модуля.

При компиляции кода Elixir через Kernel.ParallelCompiler, который используется Mix и elixirc, вызов модуля, который ещё не скомпилирован, заблокирует вызывающую сторону, пока модуль не станет доступным. Выполнение скриптов Elixir, таких как передача имени файла в elixir, ожидания не производит.

compile_file(file, relative_to \\ nil)Source

@spec compile_file(binary(), nil | binary()) :: [{module(), binary()}]

Компилирует указанный файл.

Принимает relative_to в качестве аргумента, чтобы указать местоположение файла.

Возвращает список кортежей, где первый элемент — имя модуля, а второй — его байткод (как двоичные данные). В отличие от require_file/2, оно не отслеживает имя файла скомпилированного файла.

Если вы хотите получить результат вычисления файла, а не модулей, определённых в нём, см. eval_file/2.

Для одновременной компиляции нескольких файлов см. Kernel.ParallelCompiler.compile/2.

compile_quoted(quoted, file \\ "nofile")Source

@spec compile_quoted(Macro.t(), binary()) :: [{module(), binary()}]

Компилирует процитированное выражение.

Возвращает список кортежей, где первый элемент — имя модуля, а второй — его байткод (как двоичные данные). В качестве второго аргумента может быть передан file, который будет использоваться для отчёта о предупреждениях и ошибках.

compile_string(string, file \\ "nofile")Source

@spec compile_string(List.Chars.t(), binary()) :: [{module(), binary()}]

Компилирует заданную строку.

Возвращает список кортежей, где первый элемент — имя модуля, а второй — его байткод (как двоичные данные). В качестве второго аргумента может быть передан file, который будет использоваться для отчёта о предупреждениях и ошибках.

Предупреждение: string может быть любым кодом Elixir, и код может выполняться с теми же привилегиями, что и виртуальная машина Erlang: это означает, что такой код может представлять угрозу для системы (например, выполняя системные команды). Не используйте compile_string/2 с недоверенными данными (такими как строки, полученные из сети).

compiler_options()Source

@spec compiler_options() :: map()

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

Для получения отдельных параметров см. get_compiler_option/1. Описание всех параметров см. в put_compiler_option/2.

Примеры

Code.compiler_options()
#=> %{debug_info: true, docs: true, ...}

compiler_options(opts)Source

@spec compiler_options(Enumerable.t()) :: %{optional(atom()) => boolean()}

Хранит все заданные параметры компиляции.

Изменение параметров компиляции влияет на все процессы, выполняемые в узле виртуальной машины Erlang. Для хранения отдельных параметров и описания всех параметров см. put_compiler_option/2.

Примеры

Code.compiler_options()
#=> %{debug_info: true, docs: true, ...}

delete_path(path)Source

@spec delete_path(Path.t()) :: boolean()

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

Это список каталогов, которые виртуальная машина Erlang использует для поиска модульного кода. Список файлов управляется для каждого узла виртуальной машины Erlang.

Путь расширяется с помощью Path.expand/1 перед удалением. Если пути не существует, эта функция возвращает false.

Примеры

Code.prepend_path(".")
Code.delete_path(".")
#=> true

Code.delete_path("/does_not_exist")
#=> false

ensure_compiled(module)Source

@spec ensure_compiled(module()) ::
  {:module, module()}
  | {:error, :embedded | :badfile | :nofile | :on_load_failure | :unavailable}

Аналогично ensure_compiled!/1, но указывает, что можно продолжить без указанного модуля.

В то время как ensure_compiled!/1 указывает компилятору Elixir, что можно продолжить только когда указанный модуль доступен, эта функция указывает, что компиляция может продолжиться без указанного модуля.

Если модуль успешно загружен, возвращает {:module, module}. В противном случае возвращает {:error, reason} с причиной ошибки. Если проверяемый модуль находится в тупике компиляции, эта функция возвращает {:error, :unavailable}. Недоступность не обязательно означает, что модуль не существует, просто что он в данный момент недоступен, но (возможно) станет доступным в будущем.

Поэтому, если вы можете продолжить только если модуль доступен, используйте ensure_compiled!/1 вместо этого. В частности, не делайте этого:

case Code.ensure_compiled(module) do
  {:module, _} -> module
  {:error, _} -> raise ...
end

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

ensure_compiled!(module)Source

@spec ensure_compiled!(module()) :: module()

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

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

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

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

ensure_loaded(module)Source

@spec ensure_loaded(module()) ::
  {:module, module()}
  | {:error, :embedded | :badfile | :nofile | :on_load_failure}

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

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

Если модуль успешно загружен, возвращает {:module, module}. В противном случае возвращает {:error, reason} с причиной ошибки.

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

Примеры

iex> Code.ensure_loaded(Atom)
{:module, Atom}

iex> Code.ensure_loaded(DoesNotExist)
{:error, :nofile}

ensure_loaded!(module)Source

@spec ensure_loaded!(module()) :: module()

То же, что и ensure_loaded/1, но вызывает исключение, если модуль не может быть загружен.

ensure_loaded?(module)Source

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

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

Аналогично ensure_loaded/1, но возвращает true если модуль уже загружен или был успешно загружен. В противном случае возвращает false.

Примеры

iex> Code.ensure_loaded?(Atom)
true

env_for_eval(env_or_opts)Source

Возвращает среду для вычисления.

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

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

Опции

Если env не задан, опции могут быть:

  • :file - файл, который будет рассмотрен при вычислении

  • :line - строка, с которой начинается скрипт

eval_file(file, relative_to \\ nil)Source

@spec eval_file(binary(), nil | binary()) :: {term(), binding()}

Вычисляет указанный файл.

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

В то время как require_file/2 и compile_file/2 возвращают загруженные модули и их байткод, eval_file/2 просто вычисляет содержимое файла и возвращает результат вычисления и его привязку (точно такой же результат, что и eval_string/3).

eval_quoted(quoted, binding \\ [], env_or_opts \\ [])Source

@spec eval_quoted(Macro.t(), binding(), Macro.Env.t() | keyword()) ::
  {term(), binding()}

Вычисляет содержимое, заключенное в кавычки.

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

См. eval_string/3 для описания binding и opts.

Примеры

iex> contents = quote(do: var!(a) + var!(b))
iex> {result, binding} = Code.eval_quoted(contents, [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
iex> result
3
iex> Enum.sort(binding)
[a: 1, b: 2]

Для удобства вы можете передать __ENV__/0 в качестве аргумента opts и все опции будут автоматически извлечены из текущей среды:

iex> contents = quote(do: var!(a) + var!(b))
iex> {result, binding} = Code.eval_quoted(contents, [a: 1, b: 2], __ENV__)
iex> result
3
iex> Enum.sort(binding)
[a: 1, b: 2]

eval_quoted_with_env(quoted, binding, env)Source

Вычисляет содержимое quoted с binding и env.

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

eval_string(string, binding \\ [], opts \\ [])Source

@spec eval_string(List.Chars.t(), binding(), Macro.Env.t() | keyword()) ::
  {term(), binding()}

Вычисляет содержимое, заданное string.

Аргумент binding — список привязок переменных. Аргумент opts — список опций среды.

Предупреждение: string может быть любым кодом Elixir и будет выполняться с теми же привилегиями, что и Erlang VM: это означает, что такой код может поставить под угрозу машину (например, выполнив системные команды). Не используйте eval_string/3 с ненадежными данными (такими как строки, полученные из сети).

Опции

Опции могут быть:

  • :file - файл, который будет рассмотрен при вычислении

  • :line - строка, с которой начинается скрипт

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

Возвращает кортеж вида {value, binding}, где value — значение, возвращаемое при вычислении string. Если при вычислении string произойдёт ошибка, будет возбуждено исключение.

binding — список со всеми привязками переменных после вычисления string. Ключи привязки обычно атомы, но они могут быть кортежами для переменных, определённых в другом контексте.

Примеры

iex> {result, binding} = Code.eval_string("a + b", [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
iex> result
3
iex> Enum.sort(binding)
[a: 1, b: 2]

iex> {result, binding} = Code.eval_string("c = a + b", [a: 1, b: 2], __ENV__)
iex> result
3
iex> Enum.sort(binding)
[a: 1, b: 2, c: 3]

iex> {result, binding} = Code.eval_string("a = a + b", [a: 1, b: 2])
iex> result
3
iex> Enum.sort(binding)
[a: 3, b: 2]

Для удобства вы можете передать __ENV__/0 в качестве аргумента opts и все импорты, требуемые и алиасы, определённые в текущей среде, будут автоматически перенесены:

iex> {result, binding} = Code.eval_string("a + b", [a: 1, b: 2], __ENV__)
iex> result
3
iex> Enum.sort(binding)
[a: 1, b: 2]

fetch_docs(module_or_path)Source

@spec fetch_docs(module() | String.t()) ::
  {:docs_v1, annotation, beam_language, format, module_doc :: doc_content,
   metadata, docs :: [doc_element]}
  | {:error, :module_not_found | :chunk_not_found | {:invalid_chunk, binary()}}
when annotation: :erl_anno.anno(),
     beam_language: :elixir | :erlang | atom(),
     doc_content: %{optional(binary()) => binary()} | :none | :hidden,
     doc_element:
       {{kind :: atom(), function_name :: atom(), arity()}, annotation,
        signature, doc_content, metadata},
     format: binary(),
     signature: [binary()],
     metadata: map()

Возвращает документацию для указанного модуля или пути к файлу .beam.

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

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

Возвращает терм, хранящийся в фрагменте документации в формате, определённом EEP 48 или {:error, reason} если фрагмент недоступен.

Примеры

# Module documentation of an existing module
iex> {:docs_v1, _, :elixir, _, %{"en" => module_doc}, _, _} = Code.fetch_docs(Atom)
iex> module_doc |> String.split("\n") |> Enum.at(0)
"Atoms are constants whose values are their own name."

# A module that doesn't exist
iex> Code.fetch_docs(ModuleNotGood)
{:error, :module_not_found}

format_file!(file, opts \\ [])Source

@spec format_file!(
  binary(),
  keyword()
) :: iodata()

Форматирует файл.

См. format_string!/2 для получения дополнительной информации о форматировании кода и доступных опциях.

format_string!(string, opts \\ [])Source

@spec format_string!(
  binary(),
  keyword()
) :: iodata()

Форматирует данный код string.

Форматировщик получает строку, представляющую код Elixir, и возвращает iodata, представляющую отформатированный код в соответствии с предварительно определёнными правилами.

Параметры

  • :file - файл, содержащий строку, используется для отчётов об ошибках

  • :line - строка, с которой начинается строка, используется для отчётов об ошибках

  • :line_length - длина строки, к которой следует стремиться при форматировании документа. По умолчанию 98. Это значение используется как руководство, но в некоторых ситуациях оно не соблюдается. См. раздел «Длина строки» ниже для получения дополнительной информации

  • :locals_without_parens - список ключевых слов с парами имени и арности, которые должны сохраняться без скобок, когда это возможно. Арность может быть атомом :*, что подразумевает все арности этого имени. Форматировщик уже включает список функций, и этот параметр дополняет этот список.

  • :force_do_end_blocks (с версии v1.9.0) - когда true, преобразует все встроенные использования do: ..., else: ... и т.д. в блоки do-end. По умолчанию false. Обратите внимание, что этот параметр является накопительным: как только вы установите его в true, все ключевые слова будут преобразованы. Если вы установите его в false позже, блоки do-end не будут преобразованы обратно в ключевые слова.

  • :normalize_bitstring_modifiers (с версии v1.14.0) - когда true, удаляет необоснованные скобки в известных модификаторах бистроковой строки модификаторов, например <<foo::binary()>> становится <<foo::binary>>, или добавляет скобки для пользовательских модификаторов, где <<foo::custom_type>> становится <<foo::custom_type()>>. По умолчанию true. Этот параметр изменяет AST.

Принципы проектирования

Форматировщик разрабатывался с тремя принципами.

Во-первых, форматировщик никогда не изменяет семантику кода. Это означает, что входное и выходное AST почти всегда эквивалентны. Единственные случаи, когда форматировщик изменяет AST, – это когда входное AST вызовет предупреждения компилятора, а выходное AST – нет. Случаи, когда форматировщик изменяет AST, могут быть отключены с помощью параметров форматирования, если это необходимо.

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

Форматировщик не жёстко кодирует имена. Форматировщик не будет вести себя особым образом, потому что функция называется defmodule, def или подобным образом. Этот принцип отражает цель Elixir быть расширяемым языком, где разработчики могут расширять язык с помощью новых конструкций так, как будто они являются частью языка. Когда абсолютно необходимо изменить поведение на основе имени, это поведение должно быть настраиваемым, например, параметр :locals_without_parens.

Запуск форматировщика

Форматировщик старается уместить как можно больше на одной строке и вводит переводы строк там, где это возможно, когда это невозможно.

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

Например, форматировщик может разбить длинное определение функции на несколько пунктов:

def my_function(
  %User{name: name, age: age, ...},
  arg1,
  arg2
) do
  ...
end

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

def my_function(%User{} = user, arg1, arg2) do
  %{name: name, age: age, ...} = user
  ...
end

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

def board?(board_id, %User{} = user, available_permissions, required_permissions) do
  Tracker.OrganizationMembers.user_in_organization?(user.id, board.organization_id) and
    required_permissions == Enum.to_list(MapSet.intersection(MapSet.new(required_permissions), MapSet.new(available_permissions)))
end

У кода выше очень длинные строки, и запуск форматировщика не решит эту проблему. На самом деле, форматировщик может сделать более очевидным, что у вас есть сложные выражения:

def board?(board_id, %User{} = user, available_permissions, required_permissions) do
  Tracker.OrganizationMembers.user_in_organization?(user.id, board.organization_id) and
    required_permissions ==
      Enum.to_list(
        MapSet.intersection(
          MapSet.new(required_permissions),
          MapSet.new(available_permissions)
        )
      )
end

Рассматривайте такие случаи как подсказку для рефакторинга кода:

def board?(board_id, %User{} = user, available_permissions, required_permissions) do
  Tracker.OrganizationMembers.user_in_organization?(user.id, board.organization_id) and
    matching_permissions?(required_permissions, available_permissions)
end

defp matching_permissions?(required_permissions, available_permissions) do
  intersection =
    required_permissions
    |> MapSet.new()
    |> MapSet.intersection(MapSet.new(available_permissions))
    |> Enum.to_list()

  required_permissions == intersection
end

Подводя итог: поскольку форматировщик не может изменить семантику вашего кода, иногда необходимо настроить или переработать код, чтобы получить оптимальное форматирование. Чтобы лучше понять, как управлять форматировщиком, в следующих разделах описываются случаи, когда форматировщик сохраняет кодирование пользователя, и как контролировать многострочные выражения.

Длина строки

Ещё один момент о форматировщике заключается в том, что параметр :line_length является руководством. Во многих случаях форматировщику не удаётся разбить ваш код, что означает, что он будет превышать длину строки. Например, если у вас есть длинная строка:

"this is a very long string that will go over the line length"

Форматировщик не знает, как её разбить, не изменив основополагающую синтаксическую структуру кода, поэтому вам нужно вмешаться:

"this is a very long string " <>
   "that will go over the line length"

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

Это также может появиться в блоках do/end, где ключевое слово do (или ->) может превышать длину строки, потому что форматировщик не имеет возможности ввести перевод строки удобным для чтения способом. Например, если вы делаете так:

case very_long_expression() do
end

И только ключевое слово do находится выше длины строки, Elixir не будет генерировать:

case very_long_expression()
do
end

Поэтому он предпочитает вообще не трогать строку и оставить do выше предела длины строки.

Сохранение форматирования пользователя

Форматировщик соблюдает входной формат в некоторых случаях. Они перечислены ниже:

  • Незначительные цифры в числах сохраняются как есть. Однако форматировщик всегда вставляет нижние подчеркивания для десятичных чисел с более чем 5 цифрами и преобразует шестнадцатеричные цифры в верхний регистр

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

  • Перевод строки внутри блоков сохраняется, как и во входных данных, за исключением:

    1. выражения, занимающие несколько строк, всегда будут иметь пустую строку перед и после и 2) пустые строки всегда будут сжаты в одну пустую строку
  • Выбор между ключевым словом :do и блоками do-end оставляется пользователю

  • Списки, кортежи, бистроки, карты, структуры и вызовы функций будут разбиты на несколько строк, если после открывающей скобки следует перевод строки, а перед закрывающей скобкой – перевод строки

  • Строки перед определёнными операторами (такими как операторы канала) и перед другими операторами (такими как операторы сравнения)

Вышеперечисленные поведения не гарантируются. В будущем мы можем удалить или добавить новые правила. Цель документирования заключается в том, чтобы предоставить лучшее понимание ожидаемого от форматировщика поведения.

Многострочные списки, карты, кортежи и т. п.

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

[
  foo,
  bar
]

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

[foo,
 bar]

будет отформатирован как

[foo, bar]

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

defstruct name: nil,
          age: 0

Форматировщик сохранит код с одним элементом ключевого слова на строке. Чтобы этого избежать, просто сожмите всё в одну строку.

Скобки и отсутствие скобок в вызовах функций

Elixir имеет два синтаксиса для вызовов функций: со скобками и без них. По умолчанию Elixir добавит скобки ко всем вызовам, за исключением:

  1. вызовов, которые имеют блоки do-end
  2. локальных вызовов без скобок, где имя и арность локального вызова также указаны в :locals_without_parens (за исключением вызовов с арностью 0, где компилятор всегда требует скобок)

Выбор скобок и их отсутствия также влияет на отступы. Когда вызов функции со скобками не помещается на одной строке, форматировщик вводит переводы строк вокруг скобок и отступает аргументы на два пробела:

some_call(
  arg1,
  arg2,
  arg3
)

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

some_call arg1,
          arg2,
          arg3

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

Enum.reduce(some_collection, initial_value, fn element, acc ->
  # code
end)

some_function_without_parens %{
  foo: :bar,
  baz: :bat
}

Комментарии к коду

Форматировщик также обрабатывает комментарии к коду таким образом, чтобы гарантировать, что пробел всегда добавляется между началом комментария (#) и следующим символом.

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

hello #world

будет переписан как

# world
hello

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

fn
  arg1 ->
    body1
    # comment

  arg2 ->
    body2
end

и в этом

fn
  arg1 ->
    body1

  # comment
  arg2 ->
    body2
end

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

Переводы строк

Форматировщик преобразует все переводы строк в коде из \r\n в \n.

get_compiler_option(key)Source

@spec get_compiler_option(atom()) :: term()

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

Описание всех параметров см. в put_compiler_option/2.

Примеры

Code.get_compiler_option(:debug_info)
#=> true

prepend_path(path)Source

@spec prepend_path(Path.t()) :: true | {:error, :bad_directory}

Добавляет путь в начало списка путей к коду Erlang VM.

Это список директорий, которые Erlang VM использует для поиска модулей. Список файлов управляется для каждого узла Erlang VM.

Путь расширяется с помощью Path.expand/1 перед добавлением в начало. Если такого пути не существует, возвращается ошибка.

Примеры

Code.prepend_path(".")
#=> true

Code.prepend_path("/does_not_exist")
#=> {:error, :bad_directory}

purge_compiler_modules()Source

@spec purge_compiler_modules() :: {:ok, non_neg_integer()}

Очистка модулей компилятора.

Компилятор использует временные модули для компиляции кода. Например, elixir_compiler_1, elixir_compiler_2, и так далее. В случае, если скомпилированный код хранит ссылки на анонимные функции или аналогичные, компилятор Elixir может не иметь возможности освободить эти модули, удерживая ненужное количество кода в памяти и в конечном итоге приводя к модулям, таким как elixir_compiler_12345.

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

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

Возвращает {:ok, number_of_modules_purged}.

put_compiler_option(key, value)Source

@spec put_compiler_option(atom(), term()) :: :ok

Сохраняет параметр компиляции.

Изменение параметров компиляции влияет на все процессы, работающие на данном узле Erlang VM.

Доступные параметры:

  • :docs - когда true, сохраняет документацию в скомпилированном модуле. По умолчанию true.

  • :debug_info - когда true, сохраняет отладочную информацию в скомпилированном модуле. Это позволяет инструментам статического анализа частично восстановить исходный код. Поэтому отключение :debug_info не рекомендуется, так как это убирает возможность компилятора Elixir и других инструментов предоставлять обратную связь. Если вы хотите удалить :debug_info при развертывании, инструменты, такие как mix release уже делают это по умолчанию.

  • :ignore_already_consolidated - когда true, не выводит предупреждение, когда протокол уже объединен, и добавляется новая реализация. По умолчанию false.

  • :ignore_module_conflict - когда true, не выводит предупреждение, когда модуль уже определен. По умолчанию false.

  • :relative_paths - когда true, использует относительные пути в цитатах, предупреждениях и ошибках, генерируемых компилятором. Обратите внимание, что отключение этого параметра не повлияет на предупреждения и ошибки во время выполнения. По умолчанию true.

  • :warnings_as_errors - приводит к ошибке компиляции при генерации предупреждений. По умолчанию false.

  • :no_warn_undefined (с версии v1.10.0) - список модулей и {Mod, fun, arity} кортежей, которые не будут генерировать предупреждения о том, что модуль или функция не существует во время компиляции. Передайте атом :all для отключения предупреждения обо всех неопределенных функциях. Это может быть полезно при динамической компиляции. По умолчанию [].

  • :tracers (с версии v1.10.0) - список трассеров (модулей), которые будут использоваться во время компиляции. Подробнее см. в документации к модулю. По умолчанию [].

  • :parser_options (с версии v1.10.0) - ключевое слово списка параметров, которые будут переданы парсеру при компиляции файлов. Он принимает те же параметры, что и string_to_quoted/2 (за исключением параметров, изменяющих сам AST). Это можно использовать в сочетании с трассером для получения локализованной информации о событиях, происходящих во время компиляции. По умолчанию [].

Всегда возвращает :ok. Возбуждает ошибку для недопустимых параметров.

Примеры

Code.put_compiler_option(:debug_info, true)
#=> :ok

quoted_to_algebra(quoted, opts \\ [])Source

@spec quoted_to_algebra(
  Macro.t(),
  keyword()
) :: Inspect.Algebra.t()

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

Документ алгебры можно преобразовать в строку, вызвав:

doc
|> Inspect.Algebra.format(:infinity)
|> IO.iodata_to_binary()

Для высокоуровневой функции, которая делает то же самое, см. Macro.to_string/1.

Учет форматирования

Elixir AST не содержит метаданных для литералов, таких как строки, списки или кортежи с двумя элементами, что означает, что сгенерированный документ алгебры не будет учитывать все пользовательские предпочтения, и комментарии могут быть размещены неправильно. Для получения лучших результатов можно использовать параметры :token_metadata, :unescape и :literal_encoder для string_to_quoted/2, чтобы предоставить дополнительную информацию форматировщику:

[
  literal_encoder: &{:ok, {:__block__, &2, [&1]}},
  token_metadata: true,
  unescape: false
]

Это создаст AST, содержащий информацию, такую как do начало и конец строк или разделители сигила, и путем обертывания литералов в блоки они теперь могут содержать метаданные, такие как номер строки, разделитель строк и экранированные последовательности, или форматирование целых чисел (например, 0x2a вместо 47). Однако, обратите внимание, что этот AST не является допустимым. Если вы его оцените, он не будет иметь тех же семантических свойств, что и обычный Elixir AST из-за :unescape и :literal_encoder параметры. Однако эти параметры полезны, если вы занимаетесь манипуляциями с исходным кодом, где важно сохранить пользовательские настройки и расположение комментариев.

Параметры

  • :comments - список комментариев, связанных с выражением с цитатой. По умолчанию []. Рекомендуется указать как :token_metadata, так и :literal_encoder параметры для string_to_quoted_with_comments/2 для правильного расположения комментариев

  • :escape - когда true, экранированные последовательности, такие как \n, будут экранированы в \\n. Если параметр :unescape был установлен в значение false при использовании string_to_quoted/2, установка этого параметра в значение false предотвратит двойное экранирование последовательностей. По умолчанию true.

  • :locals_without_parens - ключевое слово списка пар «имя и арность», которые необходимо сохранить без скобок, когда это возможно. Арность может быть атомом :*, что подразумевает все арности этого имени. Форматировщик уже включает список функций, и этот параметр дополняет этот список.

require_file(file, relative_to \\ nil)Source

@spec require_file(binary(), nil | binary()) :: [{module(), binary()}] | nil

Загружает указанный file.

Принимает relative_to в качестве аргумента, чтобы указать расположение файла. Если файл уже загружен, require_file/2 ничего не делает и возвращает nil.

Обратите внимание, что если require_file/2 вызывается разными процессами одновременно, первый вызвавший процесс require_file/2 приобретает блокировку, а остальные будут блокироваться, пока файл не станет доступным. Это означает, что если require_file/2 вызывается более одного раза с данным файлом, этот файл будет скомпилирован только один раз. Первый процесс, вызывающий require_file/2, получит список загруженных модулей, другие получат nil. Список загруженных файлов управляется для каждого узла Erlang VM.

См. compile_file/2, если вы хотите скомпилировать файл без отслеживания его имен. Наконец, если вы хотите получить результат оценки файла, а не модулей, определенных в нём, см. eval_file/2.

Примеры

Если файл не был загружен, он возвращает список модулей:

modules = Code.require_file("eex_test.exs", "../eex/test")
List.first(modules)
#=> {EExTest.Compiled, <<70, 79, 82, 49, ...>>}

Если файл был загружен, он возвращает nil:

Code.require_file("eex_test.exs", "../eex/test")
#=> nil

required_files()Source

@spec required_files() :: [binary()]

Список всех загруженных файлов.

Примеры

Code.require_file("../eex/test/eex_test.exs")
List.first(Code.required_files()) =~ "eex_test.exs"
#=> true
END_OF_DOCUMENT_MARKER

string_to_quoted(string, opts \\ [])Source

@spec string_to_quoted(
  List.Chars.t(),
  keyword()
) ::
  {:ok, Macro.t()}
  | {:error, {location :: keyword(), binary() | {binary(), binary()}, binary()}}

Преобразует заданную строку в её скобочную форму.

Возвращает {:ok, quoted_form} в случае успеха, {:error, {meta, message_info, token}} в противном случае.

Параметры

  • :file — имя файла, которое будет сообщено в случае ошибок разбора. По умолчанию "nofile".

  • :line — начальная строка анализируемой строки. По умолчанию 1.

  • :column — (с версии v1.11.0) начальная колонка анализируемой строки. По умолчанию 1.

  • :columns — когда true, прикрепить к скобочным данным ключ :column. По умолчанию false.

  • :unescape (с версии v1.10.0) — когда false, сохраняет эскейп-последовательности. Например, "null byte\\t\\x00" останется без изменений вместо преобразования в битовое литеральное значение. Обратите внимание, что если вы установите этот параметр в false, результирующее AST больше не будет валидным, но это может быть полезно для анализа/преобразования исходного кода, обычно в сочетании с quoted_to_algebra/2. По умолчанию true.

  • :existing_atoms_only — когда true, генерирует ошибку, когда токенизатор находит несуществующие атомы. По умолчанию false.

  • :token_metadata (с версии v1.10.0) — когда true, включает метаданные, связанные с токенами, в AST выражения, такие как метаданные для do и end токенов, для закрывающих токенов, конца выражений, а также разделителей для сигилов. См. Macro.metadata/0. По умолчанию false.

  • :literal_encoder (с версии v1.10.0) — как кодировать литералы в AST. Это должна быть функция, которая принимает два аргумента, литерал и его метаданные, и должна возвращать {:ok, ast :: Macro.t} или {:error, reason :: binary}. Если вы вернёте что-либо отличное от самого литерала в качестве term, то AST больше не будет валидным. Этот параметр может всё ещё быть полезен для текстового анализа исходного кода.

  • :static_atoms_encoder — функция кодирования статических атомов, см. раздел "Функция :static_atoms_encoder" ниже. Обратите внимание, что этот параметр переопределяет поведение :existing_atoms_only для статических атомов, но :existing_atoms_only всё ещё используется для динамических атомов, таких как атомы с интерполяциями.

  • :warn_on_unnecessary_quotes — когда false, не выводит предупреждения при наличии лишних кавычек у атомов, ключевых слов или вызовов. По умолчанию true.

Macro.to_string/2

Обратный процесс преобразования строки в её скобочную форму — Macro.to_string/2, который преобразует скобочную форму в строковое/двоичное представление.

Функция :static_atoms_encoder

Когда static_atoms_encoder: &my_encoder/2 передаётся в качестве аргумента, my_encoder/2 вызывается каждый раз, когда токенизатор должен создать "статический" атом. Статические атомы — это атомы в AST, которые работают как псевдонимы, удалённые вызовы, локальные вызовы, имена переменных, обычные атомы и списки ключевых слов.

Функция-кодировщик получит имя атома (как двоичную строку) и список ключевых слов с текущим файлом, строкой и столбцом. Она должна вернуть {:ok, token :: term} | {:error, reason :: binary}.

Функция-кодировщик должна создать атом из заданной строки. Для создания валидного AST требуется вернуть {:ok, term}, где term — атом. Возможна и возврат чего-либо помимо атома, но в этом случае AST больше не будет «валидным», поскольку не сможет быть использован для компиляции или оценки кода Elixir. Пример использования — если вы хотите использовать парсер Elixir в пользовательском интерфейсе, но не хотите исчерпать таблицу атомов.

Функция кодирования атомов не вызывается для всех атомов, присутствующих в AST. Она не будет вызвана для следующих атомов:

  • операторы (:+, :-, и так далее)

  • ключевые слова синтаксиса (fn, do, else, и так далее)

  • атомы, содержащие интерполяцию (:"#{1 + 1} is two"), поскольку эти атомы строятся во время выполнения.

string_to_quoted!(string, opts \\ [])Source

@spec string_to_quoted!(
  List.Chars.t(),
  keyword()
) :: Macro.t()

Преобразует заданную строку в её скобочную форму.

Возвращает AST в случае успеха, в противном случае генерирует исключение. Исключение — TokenMissingError в случае отсутствия токена (обычно из-за незавершенного выражения), SyntaxError в противном случае.

Смотрите string_to_quoted/2 для информации о параметрах.

string_to_quoted_with_comments(string, opts \\ [])Source

@spec string_to_quoted_with_comments(
  List.Chars.t(),
  keyword()
) ::
  {:ok, Macro.t(), [map()]} | {:error, {location :: keyword(), term(), term()}}

Преобразует заданную строку в её скобочную форму и список комментариев.

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

Возвращает {:ok, quoted_form, comments} в случае успеха, {:error, {line, error, token}} в противном случае.

Комментарии — это карты со следующими полями:

  • :line — номер строки в исходном коде

  • :text — полный текст комментария, включая ведущий #

  • :previous_eol_count — количество символов новой строки между комментарием и предыдущим узлом AST или комментарием

  • :next_eol_count — количество символов новой строки между комментарием и следующим узлом AST или комментарием

Смотрите string_to_quoted/2 для информации о параметрах.

Примеры

iex> Code.string_to_quoted_with_comments("""
...> :foo
...>
...> # Hello, world!
...>
...>
...> # Some more comments!
...> """)
{:ok, :foo, [
  %{line: 3, column: 1, previous_eol_count: 2, next_eol_count: 3, text: "# Hello, world!"},
  %{line: 6, column: 1, previous_eol_count: 3, next_eol_count: 1, text: "# Some more comments!"},
]}

iex> Code.string_to_quoted_with_comments(":foo # :bar")
{:ok, :foo, [
  %{line: 1, column: 6, previous_eol_count: 0, next_eol_count: 0, text: "# :bar"}
]}

string_to_quoted_with_comments!(string, opts \\ [])Source

@spec string_to_quoted_with_comments!(
  List.Chars.t(),
  keyword()
) :: {Macro.t(), [map()]}

Преобразует заданную строку в её скобочную форму и список комментариев.

Возвращает AST и список комментариев в случае успеха, в противном случае генерирует исключение. Исключение — TokenMissingError в случае отсутствия токена (обычно из-за незавершенного выражения), SyntaxError в противном случае.

Смотрите string_to_quoted/2 для информации о параметрах.

unrequire_files(files)Source

@spec unrequire_files([binary()]) :: :ok

Удаляет файлы из списка требуемых файлов.

Модули, определённые в файле, не удаляются; вызов этой функции только удаляет их из списка, позволяя снова потребовать их.

Список файлов управляется по узлу Erlang VM.

Примеры

# Require EEx test code
Code.require_file("../eex/test/eex_test.exs")

# Now unrequire all files
Code.unrequire_files(Code.required_files())

# Note that modules are still available
function_exported?(EExTest.Compiled, :before_compile, 0)
#=> true

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

Spec-Zone.ru

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