2

I've a simple macro that injects a function into the calling module.

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

This works as intended but because of the fact that the run function is nested inside the quote block, I'm unable to add documentation using ExDoc. I also want to define the run function outside as I feel that makes the code look better. Something like this:

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

How do I go about doing this? In addition, how do I add documentation using ExDoc for a nested function?

3
  • Do you want to add the documentation to MyModule.run or do you want it to appear in the run function you inject into the module that does use MyModule? Commented Sep 16, 2017 at 9:57
  • @Dogbert I want to add the documentation to MyModule.run and in the module that does use MyModule Commented Sep 16, 2017 at 9:59
  • @Dogbert If I define the docs for the nested run function I get the documentation in the destination module but not the original module. Commented Sep 16, 2017 at 10:03

1 Answer 1

4

You can use defdelegate inside the quote and then define run in the main module.

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 will get an auto generated doc by default which will point the user to MyModule.run/0. This can be customized by adding a @doc "" before defdelegate, if needed.

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.
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much. This works but what if the run function has arguments?
@MohideenImranKhan if you have say def add(a, b) ..., the defdelegate would be defdelegate add(a, b), to: MyModule.
@Dogbert Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.