2017-09-16 2 views
1

J'ai une macro simple qui injecte une fonction dans le module appelant.Définir la fonction hors bloc de citation dans elixir

defmodule MyModule do 
    defmacro __using__(_opts) do 
    quote do 
     def run do 
     IO.puts "Hello world" 
     end 
    end 
    end 
end 

Cela fonctionne comme prévu, mais en raison du fait que la fonction d'exécution est imbriqué dans le bloc de citation, je ne peux pas ajouter de la documentation à l'aide ExDoc. Je veux également définir la fonction d'exécution à l'extérieur car je pense que cela rend le code meilleur. Quelque chose comme ceci:

defmodule MyModule do 
    def run do 
    IO.puts "Hello world" 
    end 

    defmacro __using__(_opts) do 
    quote do 
     # Some code to inject the run function 
    end 
    end 
end 

Comment procéder? De plus, comment ajouter de la documentation en utilisant ExDoc pour une fonction imbriquée?

+0

Voulez-vous ajouter la documentation à 'MyModule.run' ou voulez-vous qu'il apparaisse dans la fonction' run' vous injectez dans le module qui ne 'utiliser MyModule'? – Dogbert

+0

@Dogbert Je souhaite ajouter la documentation à MyModule.run et dans le module qui utilise 'MyModule' –

+0

@Dogbert Si je définis les docs pour la fonction d'exécution imbriquée, je reçois la documentation dans le module de destination mais pas dans le module d'origine. –

Répondre

2

Vous pouvez utiliser defdelegate à l'intérieur du quote, puis définir run dans le module principal.

defmodule MyModule do 
    @doc """ 
    Prints "Hello world" 
    """ 
    def run do 
    IO.puts "Hello world" 
    end 

    defmacro __using__(_opts) do 
    quote do 
     defdelegate run, to: MyModule 
    end 
    end 
end 

defmodule A do 
    use MyModule 
end 

A.run/0 recevra une doc générée automatiquement par défaut qui pointera à l'utilisateur de MyModule.run/0. Cela peut être personnalisé en ajoutant un @doc "" avant defdelegate, si nécessaire.

iex(1)> MyModule.run 
Hello world 
:ok 
iex(2)> A.run 
Hello world 
:ok 
iex(3)> h(MyModule.run) 

            def run() 

Prints "Hello world" 

iex(4)> h(A.run) 

            def run() 

See MyModule.run/0. 
+0

Merci beaucoup. Cela fonctionne mais que faire si la fonction d'exécution a des arguments? –

+0

FWIW, ['Module.add_doc/6'] (https://hexdocs.pm/elixir/Module.html#add_doc/6). – mudasobwa

+0

@MohideenImranKhan Si vous avez dit 'def add (a, b) ...', le 'defdelegate' serait' defdelegate add (a, b), à: MyModule'. – Dogbert