Elixir-macros

提供:Dev Guides
移動先:案内検索

エリクサー-マクロ

マクロは、Elixirの最も高度で強力な機能の1つです。 すべての言語のすべての高度な機能と同様に、マクロは控えめに使用する必要があります。 コンパイル時に強力なコード変換を実行できます。 これから、マクロとは何か、マクロを簡単に使用する方法を理解します。

見積もり

マクロについて説明する前に、まずElixirの内部構造を見てみましょう。 Elixirプログラムは、独自のデータ構造で表すことができます。 Elixirプログラムの構成要素は、3つの要素を持つタプルです。 たとえば、関数呼び出しsum(1、2、3)は、内部的に次のように表されます-

{:sum, [], [1, 2, 3]}

最初の要素は関数名、2番目はメタデータを含むキーワードリスト、3番目は引数リストです。 次のように記述すれば、iexシェルの出力としてこれを取得できます-

quote do: sum(1, 2, 3)

演算子もそのようなタプルとして表されます。 最後の要素がリストではなくアトムであることを除いて、変数もそのようなトリプレットを使用して表されます。 より複雑な式を引用すると、コードがそのようなタプルで表されていることがわかります。このタプルは、ツリーに似た構造で互いに入れ子になっていることがよくあります。 多くの言語は、そのような表現を* Abstract Syntax Tree(AST)*と呼びます。 Elixirはこれらの引用表現を呼び出します。

引用を解除

コードの内部構造を取得できるようになったので、どのように変更しますか? 新しいコードまたは値を挿入するには、 unquote を使用します。 式の引用を解除すると、評価されてASTに挿入されます。 概念を理解するための例(iexシェル)を考えてみましょう-

num = 25

quote do: sum(15, num)

quote do: sum(15, unquote(num))

上記のプログラムが実行されると、次の結果が生成されます-

{:sum, [], [15, {:num, [], Elixir}]}
{:sum, [], [15, 25]}

引用式の例では、numを25に自動的に置き換えませんでした。 ASTを変更する場合は、この変数の引用符を外す必要があります。

マクロ

引用と非引用に精通したので、マクロを使用してElixirでメタプログラミングを探索できます。

最も簡単に言えば、マクロは、アプリケーションコードに挿入される引用符付きの式を返すように設計された特別な関数です。 マクロが関数のように呼び出されるのではなく、引用符で囲まれた式に置き換えられることを想像してください。 マクロを使用すると、Elixirを拡張し、アプリケーションにコードを動的に追加するために必要なものがすべて揃います

マクロとしての場合を除き、実装しましょう。 まず、 defmacro マクロを使用してマクロを定義します。 マクロは引用符で囲まれた式を返す必要があることに注意してください。

defmodule OurMacro do
   defmacro unless(expr, do: block) do
      quote do
         if !unquote(expr), do: unquote(block)
      end
   end
end

require OurMacro

OurMacro.unless true, do: IO.puts "True Expression"

OurMacro.unless false, do: IO.puts "False expression"

上記のプログラムが実行されると、次の結果が生成されます-

False expression

ここで起こっているのは、コードが_unless_マクロによって返される引用符で囲まれたコードに置き換えられていることです。 式を引用符で囲まずに現在のコンテキストで評価し、doブロックも引用符で囲まずにコンテキストで実行します。 この例は、エリクサーのマクロを使用したメタプログラミングを示しています。

マクロは、はるかに複雑なタスクで使用できますが、控えめに使用する必要があります。 これは、メタプログラミングは一般に悪い習慣と見なされており、必要な場合にのみ使用する必要があるためです。