當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Elixir Code用法及代碼示例


Elixir語言中 Code 相關用法介紹如下。

用於管理代碼編譯、代碼評估和代碼加載的實用程序。

該模塊補充了 Erlang 的:code 模塊以添加特定於 Elixir 的行為。這個模塊中的幾乎所有函數都對 Elixir 的行為產生了全局副作用。

處理文件

該模塊包含三個用於編譯和評估文件的函數。以下是它們及其行為的摘要:

  • require_file/2 - 編譯文件並跟蹤其名稱。如果以前需要該文件,它不會再次編譯該文件。

  • compile_file/2 - 編譯文件而不跟蹤其名稱。多次調用時多次編譯文件。

  • eval_file/2 - 評估文件內容而不跟蹤其名稱。它返回文件中最後一個表達式的結果,而不是其中定義的模塊。評估文件不會觸發下一節中說明的編譯跟蹤器。

簡而言之,當您要跟蹤係統處理的文件時,必須使用第一個,以避免多次編譯同一個文件。這在腳本中很常見。

compile_file/2 必須在您對文件中定義的模塊感興趣時使用,無需跟蹤。當您對評估文件的結果而不是它定義的模塊感興趣時,應該使用 eval_file/2

上述函數適用於 Elixir 源代碼。如果您想使用編譯為字節碼的模塊,這些模塊具有 .beam 擴展名,通常位於 Mix 項目的 _build 目錄下,請參閱 Erlang 的 :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 是導入的模塊,然後是導入的函數/宏的 namearity

  • {:alias, meta, alias, as, opts} - 每當 alias 別名為 as 時跟蹤。 meta 是別名 AST 元數據,opts 是別名選項。

  • {:alias_expansion, meta, as, alias} 跟蹤先前定義的 alias 的別名擴展,即當用戶寫入擴展為 aliasas 時。 meta 是別名擴展 AST 元數據。

  • {:alias_reference, meta, module} - 隻要代碼中有別名,即用戶在代碼中寫入 MyModule.Foo.Bar 時進行跟蹤,無論它是否被擴展。

  • {:require, meta, module, opts} - 每當需要 module 時進行跟蹤。 meta 是要求 AST 元數據,opts 是要求選項。

  • {:struct_expansion, meta, module, keys} - 每當 module 的結構展開時跟蹤。 meta 是結構 AST 元數據,keys 是擴展使用的鍵

  • {:remote_function, meta, module, name, arity}{:remote_macro, meta, module, name, arity} - 每當引用遠程函數或宏時進行跟蹤。 meta 是調用 AST 元數據,module 是調用的模塊,然後是 namearity

  • {:local_function, meta, name, arity}{:local_macro, meta, name, arity} - 每當引用本地函數或宏時跟蹤。 meta 是調用 AST 元數據,後跟 namearity

  • {:compile_env, app, path, return} - 每當調用 Application.compile_env/3 Application.compile_env!/2 時跟蹤。 app 是原子,path 是要在應用程序環境中遍曆的鍵列表,而 return{:ok, value}:error

  • {:on_module, bytecode, :none} -(自 v1.11.0 起)在定義模塊時跟蹤。這等效於 @after_compile 回調,並在給定模塊中的任何 @after_compile 之後調用。第三個元素目前是:none,但將來可能會提供更多元數據。最好暫時忽略它。

: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

相關用法


注:本文由純淨天空篩選整理自elixir-lang.org大神的英文原創作品 Code。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。