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


Elixir Macro.expand_once用法及代碼示例


Elixir語言中 Macro.expand_once 相關用法介紹如下。

用法:

expand_once(ast, env)

接收一個 AST 節點並展開一次。

展開以下內容:

如果表達式無法展開,則返回表達式本身。這個函數不遍曆AST,隻展開根節點。

expand_once/2 隻執行一次擴展。勾選 expand/2 進行擴展,直到節點不能再擴展。

例子

在下麵的示例中,我們有一個宏,它生成一個帶有名為name_length 的函數的模塊,該函數返回模塊名稱的長度。此函數的值將在編譯時計算,而不是在運行時計算。

考慮下麵的實現:

defmacro defmodule_with_length(name, do: block) do
  length = length(Atom.to_charlist(name))

  quote do
    defmodule unquote(name) do
      def name_length, do: unquote(length)
      unquote(block)
    end
  end
end

當像這樣調用時:

defmodule_with_length My.Module do
  def other_function, do: ...
end

編譯將失敗,因為引用時的My.Module 不是原子,而是語法樹,如下所示:

{:__aliases__, [], [:My, :Module]}

也就是說,我們需要將上麵的別名節點擴展為一個原子,以便我們可以檢索它的長度。擴展節點並不簡單,因為我們還需要擴展調用者別名。例如:

alias MyHelpers, as: My

defmodule_with_length My.Module do
  def other_function, do: ...
end

最終的模塊名稱將是 MyHelpers.Module 而不是 My.Module 。使用 Macro.expand/2 時,會考慮此類別名。本地和遠程宏也被擴展。我們可以重寫上麵的宏來使用這個函數:

defmacro defmodule_with_length(name, do: block) do
  expanded = Macro.expand(name, __CALLER__)
  length = length(Atom.to_charlist(expanded))

  quote do
    defmodule unquote(name) do
      def name_length, do: unquote(length)
      unquote(block)
    end
  end
end

相關用法


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