When you use a module in Elixir, the __using__/1 macro of that module is called.

In the Hello example app from Phoenix Guides, the router is defined as a module named HelloPhoenix.Router in web/router.ex. The first line of its body looks like this:

use HelloPhoenix.Web, :router

It is calling the __using__/1 macro of HelloPhoenix.Web module, with a atom :router as the parameter. If you open web/web.ex, where HelloPhoenix.Web module is defined, you can find the macro near the bottom:

@doc """
When used, dispatch to the appropriate controller/view/etc.
"""
defmacro __using__(which) when is_atom(which) do
  apply(__MODULE__, which, [])
end

__MODULE__ is one of Elixir’s read-only pseudo-variables. Similar to Erlang’s ?MODULE, it expands to the current module’s name at compile time, which in our case is HelloPhoenix.Web. As for the apply/3 function, according to Elixir documentation, it has the following signature:

apply(module, fun, args)

So in this case, the current module, an atom :router and an empty list are bind to the module, fun and args parameters respectively. What the apply function does is:

Invokes the given fun from module with the array of arguments args. Inlined by the compiler.

That means a function named router in the current module will be called with an empty list as the parameter. Let’s look at the router function:

def router do
  quote do
    use Phoenix.Router
  end
end

The code in a quote block will be turned it into its internal representation in Elixir. You can find more about quoting in the quote and unquote guide. Then we have another round of use, and now the __using__/1 macro of module Phoenix.Router will be called with no parameter, which defaults to an empty list.

Leave a comment