Use of private macros

Private macros are recognized by the compiler when used somewhere deeper
than the level when they were defined. However on the same level - nope.
Obviously, no problems with public macros wrapped in to “utility” modules.
Did I miss something?

defmodule Ext do
  defmacro digits do
    quote do
      def one, do: 1
      def two, do: 2
    end
  end
end

defmodule ViaPub do
  require Ext
  Ext.digits()    # one/1, two/2 definitions plugged to ViaPub
end

defmodule ViaPriv do
  defmacrop digits do
    quote do
      def one, do: 1
      def two, do: 2
    end
  end
  digits()  # ** (CompileError) lib/macro_use.ex:22: undefined function
digits/0
end

You can use:
a) import:

defmodule A do
  def do_a, do: :a
end

defmodule B do
  import A
  
  def do_b, do: do_a
end

IO.puts B.do_b

Any public method (def) from A module are visible only inside B module (like you declare it as defp).

b) use:

defmodule A do
  defmacro __using__(_) do
    quote do
      def do_a, do: :a
    end
  end
end

defmodule B do
  use A
end

IO.puts B.do_a

In using macro you can define public and private methods and then those methods will be included to B module and public methods could be accessible from outside.

For more details about import, use and more follow this link.

You can’t use macros in the same context they are defined. That’s because macro expansion happens before evaluation.

To define the macros in the module the module body has be evaluated and since macro expansion happens before evaluation you are expanding the macro before it’s defined.

1 Like