Elixir-マクロ
マクロは、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ブロックの引用符を外しました。この例は、elixirでマクロを使用したメタプログラミングを示しています。
マクロは、はるかに複雑なタスクで使用できますが、慎重に使用する必要があります。これは、メタプログラミングは一般的に悪い習慣と見なされており、必要な場合にのみ使用する必要があるためです。