Elixier - Makros

Makros sind eine der fortschrittlichsten und leistungsstärksten Funktionen von Elixir. Wie bei allen erweiterten Funktionen einer Sprache sollten Makros sparsam verwendet werden. Sie ermöglichen die Durchführung leistungsfähiger Codetransformationen in der Kompilierungszeit. Wir werden nun kurz verstehen, was Makros sind und wie man sie verwendet.

Zitat

Bevor wir über Makros sprechen, schauen wir uns zunächst die Elixir-Interna an. Ein Elixir-Programm kann durch eigene Datenstrukturen dargestellt werden. Der Baustein eines Elixir-Programms ist ein Tupel mit drei Elementen. Beispielsweise wird die Funktionsaufrufsumme (1, 2, 3) intern dargestellt als -

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

Das erste Element ist der Funktionsname, das zweite ist eine Schlüsselwortliste mit Metadaten und das dritte ist die Argumentliste. Sie können dies als Ausgabe in der IEX-Shell erhalten, wenn Sie Folgendes schreiben:

quote do: sum(1, 2, 3)

Operatoren werden auch als solche Tupel dargestellt. Variablen werden auch mit solchen Tripletts dargestellt, außer dass das letzte Element ein Atom anstelle einer Liste ist. Wenn wir komplexere Ausdrücke zitieren, können wir sehen, dass der Code in solchen Tupeln dargestellt wird, die häufig in einer baumähnlichen Struktur ineinander verschachtelt sind. Viele Sprachen würden solche Darstellungen alsAbstract Syntax Tree (AST). Elixir nennt diese zitierten Ausdrücke.

Unquote

Wie können wir die interne Struktur unseres Codes abrufen, nachdem wir sie abrufen können? Um neuen Code oder neue Werte einzufügen, verwenden wirunquote. Wenn wir einen Ausdruck deaktivieren, wird er ausgewertet und in den AST injiziert. Betrachten wir ein Beispiel (in der IEX-Shell), um das Konzept zu verstehen -

num = 25

quote do: sum(15, num)

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

Wenn das obige Programm ausgeführt wird, wird das folgende Ergebnis erzeugt:

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

Im Beispiel für den Anführungszeichenausdruck wurde num nicht automatisch durch 25 ersetzt. Wir müssen diese Variable aus dem Anführungszeichen entfernen, wenn wir den AST ändern möchten.

Makros

Nachdem wir nun mit Anführungszeichen und Anführungszeichen vertraut sind, können wir die Metaprogrammierung in Elixir mithilfe von Makros untersuchen.

Im einfachsten Fall sind Makros spezielle Funktionen, die einen Ausdruck in Anführungszeichen zurückgeben, der in unseren Anwendungscode eingefügt wird. Stellen Sie sich vor, das Makro wird durch den Ausdruck in Anführungszeichen ersetzt und nicht wie eine Funktion aufgerufen. Mit Makros haben wir alles Notwendige, um Elixir zu erweitern und unseren Anwendungen dynamisch Code hinzuzufügen

Lassen Sie uns implementieren, es sei denn als Makro. Wir beginnen mit der Definition des Makros mit demdefmacroMakro. Denken Sie daran, dass unser Makro einen Ausdruck in Anführungszeichen zurückgeben muss.

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"

Wenn das obige Programm ausgeführt wird, wird das folgende Ergebnis erzeugt:

False expression

Was hier passiert, ist, dass unser Code durch den zitierten Code ersetzt wird, der vom Makro "Es sei denn" zurückgegeben wird . Wir haben den Ausdruck aufgehoben, um ihn im aktuellen Kontext auszuwerten, und den do-Block, um ihn in seinem Kontext auszuführen, nicht in Anführungszeichen gesetzt. Dieses Beispiel zeigt uns die Metaprogrammierung mit Makros in Elixier.

Makros können in viel komplexeren Aufgaben verwendet werden, sollten jedoch sparsam verwendet werden. Dies liegt daran, dass Metaprogrammierung im Allgemeinen als schlechte Praxis angesehen wird und nur bei Bedarf verwendet werden sollte.