Ich habe Makros in Elixir untersucht und dann habe ich dieses Snippet gefunden in Programmierung Elixir> Kapitel 20> Verwenden von Bindungen, um Werte zu injizieren.Dynamische Funktionsdefinition mit unquote
defmodule Test do
require My
[ :fred, :bert ] |> Enum.each(&My.mydef(&1))
end
In der mydef
ist ein einfaches Makro, das für den Vornamen eine Echomethode definiert. So sollte mein Modul-Test haben zwei Funktionen fred
und bert
, dann erklärt der Autor bind_quoted
, und es verwendet unquote
innerhalb der Makro, um die Funktion zu definieren, in Folge hat.
defmodule My do
defmacro mydef(name) do
quote bind_quoted: [name: name] do
def unquote(name)(), do: unquote(name)
end
end
end
Der Autor hat gesagt, dass bind_quoted
die aufschieben würde unquote
Ausführung, damit die Methoden zur Laufzeit definiert werden können. Dann habe ich Macro.to_string verwendet, um zu analysieren, was erzeugt wurde, was mich darauf hinweist, dies zu testen.
defmodule Test do
name = :something
def unquote(name)(), do: unquote(name)
end
Test.something()
# Returns :something
Jetzt frage ich mich, wie das funktioniert. Dieser Code sollte einen Fehler auslösen, der besagt, dass unquote
nicht innerhalb eines quote
Blocks verwendet wird, und fast dasselbe für Makro mydef
, das laut Elixir-Dokumentation unquote
bei Verwendung von bind_quoted
nicht verwenden kann.
Kann jemand erklären, wie Elixir diesen Code behandelt?
Ich hatte gedacht, dass es war, weil 'def 'ein Makro ist, dann vorausgesetzt, dass Makroparameter vor dem Übergeben an das Makro selbst zitiert werden, so würde" unquote "erlaubt sein. Aber wenn ich 'My.mydef (unquote (name))' versuche, dann bekomme ich den erwarteten Fehler. Ich denke, dass es einen speziellen Umgang mit Def-Parametern gibt. –
Das ist wahr, wir können unquote auf Makro-Parameter verwenden, aber um den Wert dieses Parameters zu erhalten, müssen wir den zitierten Ausdruck ausschließen, um Aufrufe in "unquote" mit "Macro.escape (expr, unquote: true)" zu entfernen . Dann können wir einen neuen Ausdruck "zitieren", der unseren geflüchteten zitierten Ausdruck verwendet. Wir müssen jedoch daran denken, den Ausdruck zu "löschen", um seinen Wert in den Kontext des Aufrufers einzufügen, was für 'unquote (name)' als Parameter der Bezeichner 'name' ist. –
Ich könnte diese Frage beantworten, wenn Sie bitte eine einzige Frage, formatiert. Bitte entfernen Sie eine Antwort, die auf keinen Fall eine Antwort ist, entfernen Sie Kommentare, fügen Sie die wesentlichen Teile sowohl der Antwort als auch der Kommentare in die ursprüngliche Frage ein und machen Sie sie zu [MCVE] (https://stackoverflow.com/help/mcve). – mudasobwa