2016-07-29 1 views
4

Dies ist üblich Elixier:Elixir: Verwendung Makro im Körper des gleichen Moduls, das es definiert

defmodule Fizz do 
    defmacro asdf, do: IO.puts("asdf") 
end 

defmodule Buzz do 
    require Fizz 
    Fizz.asdf 
end 

Doch obwohl Sie Makros im gleichen Kontext wie verweisen können:

defmodule Fizz do 
    # ... 
    defmacro asdf_qwer, do: asdf && IO.puts("qwer") 
end 

.. . Sie können Makros im Körper des gleichen Moduls nicht verweisen, die sie definiert:

defmodule Fizz do 
    defmacro asdf, do: IO.puts("asdf") 
    asdf 
end 

Dies erhöht undefined function asdf/0.

Gibt es einen Workaround für dieses "Problem"? Manchmal möchte ich Makros verwenden, um einige Boilerplate aus dem Modul, an dem ich arbeite, zu entfernen, und die Funktionalität dieses Makros kann spezifisch genug sein, um es nicht in ein anderes Modul zu integrieren.

Antwort

1

Der Grund, warum wir undefined function Fehler hier erhalten, ist, weil zur Kompilierungszeit, das asdf Makro noch nicht existiert.

Daher müssen wir den Compiler benachrichtigen, dass ein zusätzlicher Schritt erforderlich ist, bevor die Kompilierung abgeschlossen ist.

Eine Option ist das Modul Callback-Attribut @after_compile, mit dem Sie kurz nach dem Kompilieren einen Code aufrufen können, um eine letzte Codegenerierung durchzuführen.

Zum Beispiel:

defmodule M do 
    @after_compile __MODULE__ 

    def __after_compile__(env, _bytecode) do 
    IO.inspect env 
    end 
end 

Eine weitere Option ist die Makros in einem Fizz.Macros Modul zu setzen.

Verwandte Themen