Код
Утилиты для управления компиляцией кода, оценкой кода и загрузкой кода.
Этот модуль дополняет модуль Erlang’s :code, добавляя поведение, специфичное для Elixir. Почти все функции в этом модуле оказывают глобальное побочное действие на поведение Elixir.
Обзор
Функции
- append_path(path)
-
Добавляет путь в конец списка путей кода виртуальной машины Erlang.
- available_compiler_options()
-
Возвращает список доступных опций компилятора.
- compile_quoted(quoted, file \\ "nofile")
-
Компилирует выражение в форме quote.
- compile_string(string, file \\ "nofile")
-
Компилирует заданную строку.
- compiler_options()
-
Получает опции компиляции из сервера кода.
- compiler_options(opts)
-
Устанавливает опции компиляции.
- delete_path(path)
-
Удаляет путь из списка путей кода виртуальной машины Erlang. Это список каталогов, которые Erlang VM использует для поиска кода модулей.
- ensure_compiled(module)
-
Обеспечивает, что указанный модуль скомпилирован и загружен.
- ensure_compiled?(module)
-
Обеспечивает, что указанный модуль скомпилирован и загружен.
- ensure_loaded(module)
-
Обеспечивает, что указанный модуль загружен.
- ensure_loaded?(module)
-
Обеспечивает, что указанный модуль загружен.
- eval_file(file, relative_to \\ nil)
-
Оценивает данный файл.
- eval_quoted(quoted, binding \\ [], opts \\ [])
-
Вычисляет содержимое в форме quote.
- eval_string(string, binding \\ [], opts \\ [])
-
Вычисляет содержимое, заданное
string. - format_file!(file, opts \\ [])
-
Форматирует файл.
- format_string!(string, opts \\ [])
-
Форматирует заданный код
string. - get_docs(module, kind)
-
Возвращает документацию для данного модуля.
- load_file(file, relative_to \\ nil)
-
Загружает данный файл.
- loaded_files()
-
Выводит список всех загруженных файлов.
- prepend_path(path)
-
Добавляет путь в начало списка путей кода виртуальной машины Erlang.
- require_file(file, relative_to \\ nil)
-
Требует указанный
file. - string_to_quoted(string, opts \\ [])
-
Преобразует заданную строку в ее форму quote.
- string_to_quoted!(string, opts \\ [])
-
Преобразует заданную строку в ее форму quote.
- unload_files(files)
-
Удаляет файлы из списка загруженных файлов.
Функции
append_path(path)
append_path(Path.t()) :: true | {:error, :bad_directory} Добавляет путь в конец списка путей кода виртуальной машины Erlang.
Это список каталогов, которые Erlang VM использует для поиска кода модулей.
Путь расширяется с помощью Path.expand/1 перед добавлением. Если этого пути не существует, возвращается ошибка.
Примеры
Code.append_path(".")
#=> true
Code.append_path("/does_not_exist")
#=> {:error, :bad_directory} available_compiler_options()
available_compiler_options() :: [atom()]
Возвращает список доступных опций компилятора.
См. compiler_options/1 для получения дополнительной информации.
Примеры
iex> Code.available_compiler_options [:docs, :debug_info, :ignore_module_conflict, :relative_paths, :warnings_as_errors]
compile_quoted(quoted, file \\ "nofile")
compile_quoted(Macro.t(), binary()) :: [{module(), binary()}] Компилирует выражение в форме quote.
Возвращает список кортежей, где первый элемент — имя модуля, а второй — его байткод (как двоичное значение). В качестве второго аргумента может быть передан file, который будет использоваться для сообщения о предупреждениях и ошибках.
compile_string(string, file \\ "nofile")
compile_string(List.Chars.t(), binary()) :: [{module(), binary()}] Компилирует заданную строку.
Возвращает список кортежей, где первый элемент — имя модуля, а второй — его байткод (как двоичное значение). В качестве второго аргумента может быть передан file, который будет использоваться для сообщения о предупреждениях и ошибках.
Для компиляции нескольких файлов одновременно см. Kernel.ParallelCompiler.compile/2.
compiler_options()
compiler_options() :: %{optional(atom()) => boolean()} Получает опции компиляции из сервера кода.
См. compiler_options/1 для получения дополнительной информации.
Примеры
Code.compiler_options()
#=> %{debug_info: true, docs: true,
#=> warnings_as_errors: false, ignore_module_conflict: false} compiler_options(opts)
compiler_options(Enumerable.t()) :: %{optional(atom()) => boolean()} Устанавливает опции компиляции.
Эти опции являются глобальными, так как хранятся сервером кода Elixir.
Доступные опции:
-
:docs- еслиtrue, сохранять документацию в скомпилированном модуле. По умолчаниюtrue. -
:debug_info- еслиtrue, сохранять отладочную информацию в скомпилированном модуле. Это позволяет разработчику восстановить исходный код. По умолчаниюfalse. -
:ignore_module_conflict- еслиtrue, перезаписывать уже определенные модули без генерации ошибок. По умолчаниюfalse. -
:relative_paths- еслиtrue, использовать относительные пути в узлах quote, предупреждениях и ошибках, сгенерированных компилятором. Отключение этой опции не повлияет на предупреждения и ошибки во время выполнения. По умолчаниюtrue. -
:warnings_as_errors- заставляет компиляцию завершиться неудачно, если были сгенерированы предупреждения. По умолчаниюfalse.
Возвращает новую карту опций компиляции.
Примеры
Code.compiler_options(debug_info: true)
#=> %{debug_info: true, docs: true,
#=> warnings_as_errors: false, ignore_module_conflict: false} delete_path(path)
delete_path(Path.t()) :: boolean()
Удаляет путь из списка путей кода виртуальной машины Erlang. Это список каталогов, которые Erlang VM использует для поиска кода модулей.
Путь расширяется с помощью Path.expand/1 перед удалением. Если пути не существует, эта функция возвращает false.
Примеры
Code.prepend_path(".")
Code.delete_path(".")
#=> true
Code.delete_path("/does_not_exist")
#=> false ensure_compiled(module)
ensure_compiled(module()) ::
{:module, module()}
| {:error, :embedded | :badfile | :nofile | :on_load_failure} Обеспечивает, что указанный модуль скомпилирован и загружен.
Если модуль уже загружен, выполняется как no-op. Если модуль еще не был загружен, проверяется, нужно ли его скомпилировать, а затем пытается загрузить.
Если загрузка модуля удалась, возвращается {:module, module}. В противном случае возвращается {:error, reason} с причиной ошибки.
См. ensure_loaded/1 для получения дополнительной информации о загрузке модулей и о том, когда использовать ensure_loaded/1 или ensure_compiled/1.
ensure_compiled?(module)
ensure_compiled?(module()) :: boolean()
Обеспечивает, что указанный модуль скомпилирован и загружен.
Аналогично ensure_compiled/1, но возвращает true если модуль уже загружен или был успешно загружен и скомпилирован. В противном случае возвращает false.
ensure_loaded(module)
ensure_loaded(module()) ::
{:module, module()}
| {:error, :embedded | :badfile | :nofile | :on_load_failure} Обеспечивает, что указанный модуль загружен.
Если модуль уже загружен, выполняется как no-op. Если модуль еще не был загружен, пытается загрузить его.
Если загрузка модуля удалась, возвращается {:module, module}. В противном случае возвращается {:error, reason} с причиной ошибки.
Загрузка кода в Erlang VM
Erlang имеет два режима загрузки кода: интерактивный и встроенный.
По умолчанию Erlang VM работает в интерактивном режиме, где модули загружаются по мере необходимости. В режиме встраивания происходит обратное, так как все модули должны быть загружены заранее или явно.
Поэтому эта функция используется для проверки, загружен ли модуль перед его использованием, и позволяет соответствующим образом отреагировать. Например, модуль URI использует эту функцию для проверки наличия определенного парсера для заданной схемы URI.
ensure_compiled/1
Elixir также содержит функцию ensure_compiled/1, которая является надмножеством ensure_loaded/1.
Поскольку компиляция Elixir происходит параллельно, в некоторых ситуациях вам может потребоваться использовать модуль, который еще не был скомпилирован, поэтому его даже нельзя загрузить.
При вызове ensure_compiled/1 компиляция вызывающего элемента приостанавливается до тех пор, пока модуль, переданный ensure_compiled/1, не станет доступен или все файлы текущего проекта не будут скомпилированы. Если компиляция завершается, а модуль недоступен, возвращается кортеж с ошибкой.
ensure_compiled/1 не применяется к зависимостям, так как зависимости должны быть скомпилированы предварительно.
В большинстве случаев ensure_loaded/1 достаточно. ensure_compiled/1 необходимо использовать в редких случаях, обычно связанных с макросами, которые нуждаются в вызове модуля для получения информации о вызовах.
Примеры
iex> Code.ensure_loaded(Atom)
{:module, Atom}
iex> Code.ensure_loaded(DoesNotExist)
{:error, :nofile} ensure_loaded?(module)
ensure_loaded?(module()) :: boolean()
Убеждается, что заданный модуль загружен.
Аналогично ensure_loaded/1, но возвращает true, если модуль уже загружен или был успешно загружен. В противном случае возвращает false.
Примеры
iex> Code.ensure_loaded?(Atom) true
eval_file(file, relative_to \\ nil)
eval_file(binary(), nil | binary()) :: {term(), binding :: list()} Вычисляет данный файл.
Принимает relative_to в качестве аргумента, чтобы указать, где находится файл.
В то время как load_file/2 загружает файл и возвращает загруженные модули и их байткод, eval_file/2 просто вычисляет содержимое файла и возвращает результат вычисления и его связи (точно такой же результат, как у eval_string/3).
eval_quoted(quoted, binding \\ [], opts \\ [])
eval_quoted(Macro.t(), list(), Macro.Env.t() | keyword()) ::
{term(), binding :: list()} Вычисляет содержимое с цитированием.
Предупреждение: Вызов этой функции внутри макроса считается плохой практикой, так как она будет пытаться вычислить значения во время выполнения во время компиляции. Аргументы макроса обычно преобразуются путем их извлечения из цитирования в возвращаемых цитируемых выражениях (вместо вычисления).
См. eval_string/3 для описания связей и параметров.
Примеры
iex> contents = quote(do: var!(a) + var!(b))
iex> Code.eval_quoted(contents, [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
{3, [a: 1, b: 2]} Для удобства вы можете передать __ENV__/0 в качестве аргумента opts , и все параметры будут автоматически извлечены из текущей среды:
iex> contents = quote(do: var!(a) + var!(b))
iex> Code.eval_quoted(contents, [a: 1, b: 2], __ENV__)
{3, [a: 1, b: 2]} eval_string(string, binding \\ [], opts \\ [])
eval_string(List.Chars.t(), list(), Macro.Env.t() | keyword()) ::
{term(), binding :: list()} Вычисляет содержимое, заданное string.
Аргумент binding представляет собой список ключевых слов со связыванием переменных. Аргумент opts — список ключевых слов с параметрами среды.
Предупреждение: string может представлять любой код Elixir и будет выполняться с теми же привилегиями, что и Erlang VM: это означает, что такой код может поставить под угрозу машину (например, выполняя системные команды). Не используйте eval_string/3 с недоверенным вводом (например, строками, поступающими из сети).
Параметры
Параметры могут быть:
-
:file— файл, который будет рассматриваться при вычислении -
:line— строка, с которой начинается скрипт
Кроме того, можно настроить следующие значения области видимости:
-
:aliases— список кортежей с псевдонимом и его целевым значением -
:requires— список необходимых модулей -
:functions— список кортежей, где первый элемент — модуль, а второй — список импортированных имён функций и их арности; список имён функций и арности должен быть отсортирован -
:macros— список кортежей, где первый элемент — модуль, а второй — список импортированных имён макросов и их арности; список имён макросов и арности должен быть отсортирован
Обратите внимание, что установка любого из вышеперечисленных значений переопределяет значения по умолчанию Elixir. Например, установка :requires в [] больше не будет автоматически требовать модуль Kernel. Аналогично, установка :macros больше не будет автоматически импортировать макросы Kernel, такие как Kernel.if/2, Kernel.SpecialForms.case/2 и т.д.
Возвращает кортеж вида {value, binding}, где value — значение, возвращаемое при вычислении string. Если при вычислении string произошла ошибка, будет поднято исключение.
binding — список ключевых слов со значением всех связей переменных после вычисления string. Ключ связи обычно представляет собой атом, но может быть кортежем для переменных, определённых в другом контексте.
Примеры
iex> Code.eval_string("a + b", [a: 1, b: 2], file: __ENV__.file, line: __ENV__.line)
{3, [a: 1, b: 2]}
iex> Code.eval_string("c = a + b", [a: 1, b: 2], __ENV__)
{3, [a: 1, b: 2, c: 3]}
iex> Code.eval_string("a = a + b", [a: 1, b: 2])
{3, [a: 3, b: 2]} Для удобства вы можете передать __ENV__/0 в качестве аргумента opts , и все импорты, требования и псевдонимы, определённые в текущей среде, будут автоматически перенесены:
iex> Code.eval_string("a + b", [a: 1, b: 2], __ENV__)
{3, [a: 1, b: 2]} format_file!(file, opts \\ [])
format_file!(binary(), keyword()) :: iodata()
Форматирует файл.
См. format_string!/2 для получения более подробной информации о форматировании кода и доступных параметрах.
format_string!(string, opts \\ [])
format_string!(binary(), keyword()) :: iodata()
Форматирует данный код string.
Форматировщик получает строку, представляющую код Elixir, и возвращает iodata, представляющую отформатированный код в соответствии с предварительно определёнными правилами.
Параметры
-
:file— файл, содержащий строку, используемый для сообщений об ошибках -
:line— строка, с которой начинается строка, используемая для сообщений об ошибках -
:line_length— длина строки, на которую следует ориентироваться при форматировании документа. По умолчанию равна 98. -
:locals_without_parens— список пар «имя–арность», которые необходимо сохранять без скобок, когда это возможно. Арность может быть атомом:*, что подразумевает все арности этого имени. Форматировщик уже включает список функций, а этот параметр дополняет этот список. -
:rename_deprecated_at— переименовать все известные устаревшие функции на указанную версию в их не устаревшие эквиваленты. Ожидает допустимую версиюVersion, которая обычно является минимальной версией Elixir, поддерживаемой проектом.
Принципы проектирования
Форматировщик был разработан на основе трёх принципов.
Во-первых, форматировщик по умолчанию никогда не изменяет семантику кода. Это означает, что AST на входе и AST на выходе эквивалентны. Допустимо необязательное поведение, такое как :rename_deprecated_at, нарушающее это гарантию.
Второй принцип заключается в предоставлении как можно меньше параметров конфигурации. Это облегчает принятие форматировщика, устраняя точки разногласий и гарантируя, что сообщество в целом придерживается единого стиля.
Форматировщик не жёстко кодирует имена. Форматировщик не будет вести себя по-особенному, потому что функция называется defmodule, def и т. д. Этот принцип отражает цель Elixir как расширяемого языка, где разработчики могут расширять язык новыми конструкциями, как будто они являются частью языка. Когда абсолютно необходимо изменить поведение на основе имени, это поведение должно быть настраиваемым, например, параметр :locals_without_parens.
Сохранение форматирования пользователя
Форматировщик в некоторых случаях соблюдает входной формат. Они перечислены ниже:
-
Незначительные цифры в числах сохраняются как есть. Однако форматировщик всегда вставляет нижние подчёркивания для десятичных чисел с более чем 5 цифрами и преобразует шестнадцатеричные цифры в верхний регистр
-
Строки, списки символов, атомы и сигилы сохраняются как есть. Ни один символ не экранируется или деэкранируется автоматически. Выбор разделителя также сохраняется из входных данных
-
Новые строки внутри блоков сохраняются так же, как и на входе, за исключением: 1) выражения, занимающие несколько строк, всегда будут иметь пустую строку перед и после, и 2) пустые строки всегда сжимаются в одну пустую строку
-
Выбор между
:doключевыми словами иdo/endблоками остаётся за пользователем -
Списки, кортежи, битовые строки, карты, структуры и вызовы функций будут разбиты на несколько строк, если за открывающей скобкой следует новая строка и перед закрывающей скобкой — новая строка
-
Операторы конвейера, такие как
|>и другие с таким же приоритетом, будут занимать несколько строк, если они занимали несколько строк на входе
Вышеперечисленные особенности не гарантируются. Мы можем в будущем удалить или добавить новые правила. Цель их документирования заключается в том, чтобы лучше понять, чего ожидать от форматировщика.
Настройка отформатированного вывода
Форматировщик пытается разместить код по возможности на одной строке. Когда код не помещается на одной строке, форматировщик вставляет разрывы строк в код.
В некоторых редких случаях это может привести к нежелательному форматированию. Например, код ниже:
"this is a very long string ... #{inspect(some_value)}" может быть отформатирован как:
"this is a very long string ... #{
inspect(some_value)
}" Это происходит потому, что единственное место, где форматировщик может вставить новую строку без изменения семантики кода, — это в интерполяции. В таких сценариях мы рекомендуем разработчикам непосредственно корректировать код. Здесь мы можем использовать бинарный оператор конкатенации <>:
"this is a very long string " <>
"... #{inspect(some_value)}" Конкатенация строк позволяет разместить код на одной строке и также предоставляет форматировщику больше вариантов.
Аналогичный пример — когда форматировщик разбивает определение функции на несколько пунктов:
def my_function(
%User{name: name, age: age, ...},
arg1,
arg2
) do Хотя код выше полностью корректен, вы можете предпочесть сопоставление переменных структуры внутри тела функции, чтобы сохранить определение на одной строке:
def my_function(%User{} = user, arg1, arg2) do
%{name: name, age: age, ...} = user Так как форматировщик не может изменить семантику вашего кода, иногда необходимо подкорректировать код, чтобы получить оптимальное форматирование.
Многострочные списки, карты, кортежи и т. д.
Вы можете принудительно сделать списки, кортежи, битовые строки, карты, структуры и вызовы функций многострочными, добавив новую строку после открывающей скобки и новой строки перед закрывающей скобкой. Например:
[ foo, bar ]
Если вокруг скобок нет новых строк, форматировщик попытается поместить всё на одну строку, так что фрагмент ниже
[foo, bar]
будет отформатирован как
[foo, bar]
Вы также можете принудительно сделать вызовы функций и ключевые слова многострочными, поместив каждый элемент на отдельную строку:
defstruct name: nil,
age: 0 Форматировщик сохранит код выше с одним ключевым словом на строке. Чтобы этого избежать, просто поместите всё в одну строку.
Скобки и отсутствие скобок в вызовах функций
В Elixir есть два синтаксиса для вызовов функций. С круглыми скобками и без них. По умолчанию Elixir добавляет скобки ко всем вызовам, за исключением:
- вызовов с блоками do/end
- локальных вызовов без скобок, где имя и арность локального вызова также указаны в
:locals_without_parens
Выбор скобок и отсутствие скобок также влияет на отступы. Когда вызов функции со скобками не помещается на одной строке, форматировщик вставляет новую строку вокруг скобок и отступает аргументы на две позиции:
some_call( arg1, arg2, arg3 )
С другой стороны, вызовы функций без скобок всегда отступают на длину самого вызова функции, как показано ниже:
some_call arg1,
arg2,
arg3 Если последний аргумент — это структура данных, такая как карты и списки, и начало структуры данных помещается на одной строке с вызовом функции, тогда отступ не применяется, это позволяет писать код такого вида:
Enum.reduce(some_collection, initial_value, fn element, acc ->
# code
end)
some_funtion_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 рассматриваются как эквивалентные (вложенность отбрасывается вместе с большей частью форматирования пользователем). В таких случаях форматировщик кода всегда форматирует по последнему варианту.
get_docs(module, kind)
get_docs(module(), :all) :: keyword() | nil
get_docs(module(), :type_docs) :: [{type, line, kind, doc}] | nil
when type: {atom(), arity()},
line: pos_integer(),
kind: atom(),
doc: nil | false | binary()
get_docs(module(), :callback_docs) :: [{callback, line, kind, doc}] | nil
when callback: {atom(), arity()},
line: pos_integer(),
kind: atom(),
doc: nil | false | binary()
get_docs(module(), :docs) :: [{function, line, kind, list(), doc}] | nil
when function: {atom(), arity()},
line: pos_integer(),
kind: atom(),
doc: nil | false | binary()
get_docs(module(), :moduledoc) ::
{line :: pos_integer(), doc :: false | binary()} | nil Возвращает документацию для заданного модуля.
При задании имени модуля он находит его BEAM-код и считывает документацию из него.
При задании пути к .beam файлу он загрузит документацию непосредственно из этого файла.
Значение возврата зависит от kind значения:
-
:moduledoc- кортеж{line, doc}гдеline— строка, с которой начинается определение модуля, аdoc— строка, прикреплённая к модулю с помощью@moduledocатрибута,falseесли использовался@moduledoc false, илиnilесли@moduledocне использовался. -
:docs- список всех строковых описаний, прикреплённых к функциям и макросам с помощью@docатрибута. Каждый кортеж имеет вид{{name, arity}, line, kind, arguments, doc}.docможет быть строкой,falseесли использовался@doc false, илиnilесли описание не использовалось. -
:callback_docs- список всех строковых описаний, прикреплённых к@callbacksс помощью@docатрибута. Каждый кортеж имеет вид{{name, arity}, line, kind, doc}.docможет быть строкой илиnilесли@docне был задан. -
:type_docs- список всех строковых описаний, прикреплённых к@typeобратным вызовам с помощью@typedocатрибута. Каждый кортеж имеет вид{{name, arity}, line, kind, doc}.docможет быть строкой илиnilесли@typedocне использовался. -
:all- список ключевых слов с:docs,:moduledoc,:callback_docs, и:type_docs.
Если модуль не найден, возвращается nil.
Примеры
# Module documentation of an existing module
iex> {_line, text} = Code.get_docs(Atom, :moduledoc)
iex> text |> String.split("\n") |> Enum.at(0)
"Convenience functions for working with atoms."
# A module that doesn't exist
iex> Code.get_docs(ModuleNotGood, :all)
nil load_file(file, relative_to \\ nil)
load_file(binary(), nil | binary()) :: [{module(), binary()}] Загружает заданный файл.
Принимает relative_to в качестве аргумента, чтобы указать, где находится файл. Если файл уже был потребован/загружен, загружает его снова.
Возвращает список кортежей {ModuleName, bytecode}, по одному кортежу для каждого модуля, определённого в файле.
Обратите внимание, что если load_file/2 вызывается различными процессами одновременно, целевой файл будет загружен многократно параллельно. Обратитесь к require_file/2, если вы не хотите, чтобы файл загружался параллельно.
Примеры
modules = Code.load_file("eex_test.exs", "../eex/test")
List.first(modules)
#=> {EExTest.Compiled, <<70, 79, 82, 49, ...>>} loaded_files()
loaded_files() :: [binary()]
Перечисляет все загруженные файлы.
Примеры
Code.require_file("../eex/test/eex_test.exs")
List.first(Code.loaded_files()) =~ "eex_test.exs"
#=> true prepend_path(path)
prepend_path(Path.t()) :: true | {:error, :bad_directory} Добавляет путь в начало списка путей к коду Erlang VM.
Это список каталогов, используемых Erlang VM для поиска кода модулей.
Путь расширяется с помощью Path.expand/1 перед добавлением в начало. Если этот путь не существует, возвращается ошибка.
Примеры
Code.prepend_path(".")
#=> true
Code.prepend_path("/does_not_exist")
#=> {:error, :bad_directory} require_file(file, relative_to \\ nil)
require_file(binary(), nil | binary()) :: [{module(), binary()}] | nil Требует указанный file файл.
Принимает relative_to в качестве аргумента, чтобы указать, где находится файл. Возвращаемое значение такое же, как у load_file/2. Если файл уже был потребован или загружен, require_file/2 ничего не делает и возвращает nil.
Обратите внимание, что если require_file/2 вызывается различными процессами одновременно, первый процесс, вызвавший require_file/2, получает блокировку, а остальные будут блокироваться до тех пор, пока файл не станет доступным. Это означает, что если require_file/2 вызывается более одного раза с заданным файлом, этот файл будет загружен только один раз. Первый процесс, вызвавший require_file/2, получит список загруженных модулей, другие получат nil.
Обратитесь к load_file/2, если вы хотите загрузить файл несколько раз. Также см. unload_files/1.
Примеры
Если код уже загружен, возвращается nil:
Code.require_file("eex_test.exs", "../eex/test")
#=> nil Если код ещё не загружен, возвращается то же, что и load_file/2:
modules = Code.require_file("eex_test.exs", "../eex/test")
List.first(modules)
#=> {EExTest.Compiled, <<70, 79, 82, 49, ...>>} string_to_quoted(string, opts \\ [])
string_to_quoted(List.Chars.t(), keyword()) ::
{:ok, Macro.t()} | {:error, {line :: pos_integer(), term(), term()}} Преобразует заданную строку в её строковое представление.
Возвращает {:ok, quoted_form} при успехе, {:error, {line, error, token}} в противном случае.
Параметры
-
:file- имя файла, которое будет указано в случае ошибок разбора. По умолчанию «nofile». -
:line- начальная строка анализируемой строки. По умолчанию 1. -
:columns- приtrue, прикрепить ключ:columnк метаданным в кавычках. По умолчаниюfalse. -
:existing_atoms_only- приtrue, генерировать ошибку, если встречаются не существующие атомы при токенизации. По умолчаниюfalse.
Macro.to_string/2
Обратным процессом преобразования строки в её кавычное представление является Macro.to_string/2, который преобразует кавычное представление в строку/бинарное представление.
string_to_quoted!(string, opts \\ [])
string_to_quoted!(List.Chars.t(), keyword()) :: Macro.t()
Преобразует заданную строку в её кавычное представление.
Возвращает ast при успехе, в противном случае генерирует исключение. Исключение — TokenMissingError в случае отсутствия токена (обычно потому, что выражение неполное), SyntaxError в противном случае.
См. string_to_quoted/2 для информации о параметрах.
unload_files(files)
unload_files([binary()]) :: :ok
Удаляет файлы из списка загруженных файлов.
Модули, определённые в файле, не удаляются; вызов этой функции только удаляет их из списка, позволяя их повторно потребовать.
Примеры
# Load EEx test code, unload file, check for functions still available
Code.load_file("../eex/test/eex_test.exs")
Code.unload_files(Code.loaded_files())
function_exported?(EExTest.Compiled, :before_compile, 0)
#=> true
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.6.6/Code.html