In Phoenix apps, the web module provides this “re-dispatch into methods” technique for use (see __using__):
defmodule ExampleWeb.Router do
use ExampleWeb, :router
end
defmodule ExampleWeb.TodoController do
use ExampleWeb, :controller
end
defmodule ExampleWeb.Layouts do
use ExampleWeb, :html
end
defmodule ExampleWeb do
@doc """
When used, dispatch to the appropriate controller/live_view/etc.
"""
defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end
def router do
#
end
def controller do
quote do
# ...
end
end
def html do
quote do
# ...
end
end
end
What was the goal/benefit behind doing it that way? I’m guessing it’s for cutting on boilerplate, as otherwise it would’ve been:
defmodule ExampleWeb.TodoController do
use ExampleWeb.Controller
end
defmodule ExampleWeb.Layouts do
use ExampleWeb.HTML
end
defmodule ExampleWeb.Router do
# hmm, probably inlined because same module name
end
defmodule ExampleWeb.Controller do
defmacro __using__ do
# ...
end
end
defmodule ExampleWeb.HTML do
defmacro __using__ do
# ...
end
end
Do we see more examples of this technique being used in libraries and projects besides Phoenix?
I’m trying to grasp the philosophy behind every decision ![]()






















