Same reasoning as to why apply(module, fun, args) has the function name supplied as an atom: It’s the only non macro-magic way to pass a module and function to be called later without the overhead of a closure. Also keep in mind that phoenix is doing the namespaceing of controllers for you, so PageController isn’t even an existing module without the namespace prepended.
I’m guessing that @edgarjrg meant something more like get("/", &PageController.index/2) which is a similar API to how Absinthe defines references to resolver functions.
Well in that case it’s because phoenix doesn’t call that function, rather it calls the ‘call’ function on the module, then the ‘action’ function on that module, which then sets up some other state and error handlers and so forth and ‘then’ calls that function on the same module, so it needs to know both the module and function on that module to call as it calls ‘other’ functions on that same module.
As @OvermindDL1 said, PageController.index is the same as PageController.index() so you probably meant &PageController.index/2. But the problem is that Phoenix do not call that function, at least not directly. What Phoenix does though is to call PageController.call(conn, :index). You can see this by yourself by creating plug like
defmodule MyPseudoController do
@behaviour Plug
@impl true
def init(opts), do: opts
@impl true
def call(conn, args) do
Plug.Conn.send_resp(conn, 200, inspect(args))
end
end
Yes i actually meant get("/", &PageController.index/2), thank you all for the answers , it looked like unnecessary complexity but i see it’s the way for decoupling scope, and allow a lot of other steps to be performed, as well as to avoid recompiling, very interesting approach.