Understanding Phoenix router

In a newly generate phoneix project there is a file hello_web.ex file which has the following code

def router do
    quote do
      use Phoenix.Router
      import Plug.Conn
      import Phoenix.Controller
    end
  end

  defmacro __using__(which) when is_atom(which) do
    apply(__MODULE__, which, [])
  end

What I dont understand here is the use of quote inside router function.

quote will return AST of the contents inside the do end block so how is that helping?why not remove quote and use it like this?

def router do
      use Phoenix.Router
      import Plug.Conn
      import Phoenix.Controller
  end

In MyAppWeb.Router, there’s use MyAppWeb, :router, which calls the macro MyAppWeb.__using__(:router), which in turn returns the return value of MyAppWeb.router/0. As macros (__using__) do receive AST and need to return AST it further means router/0 does need to return AST. MyAppWeb.router/0 is not meant to ever be called from a place not within a macro. Maybe they should even be private functions.

3 Likes

While I’m not sure that it addresses you concerns directly, it may clarify some related grey areas:

In addition I’d recommend exploring the Elixir compilation process a bit - to start have a look at

https://medium.com/@fxn/how-does-elixir-compile-execute-code-c1b36c9ec8cf

1 Like

I read your other answer in the forum Why/How/When to use the __using__(which) macro in Phoenix Controller/View/etc?

That was helpful.

So far this is what I understood:

using will execute during compile-time, not run time. So if I move the code

use Phoenix.Router
import Plug.Conn
import Phoenix.Controller

to router.ex

   use HelloWeb, :router

  use Phoenix.Router
  import Plug.Conn
  import Phoenix.Controller

it will work fine because that will be evaluated in runtime.

You’re only halfway there.

use Phoenix.Router

will also be replaced at compile time.

Main phases of Elixir compilation

 Scanning
     ↓ 
 Parsing
     ↓ 
 Expansion
   ↓   ↑
Translation
   ↓   ↑
 Execution

Notice how Expansion, Translation and Execution form a loop that continues until there is nothing left to expand.