I'm new to Elixir and Phoenix and trying to wrap my head around some of the syntax. Looking at the basic HelloWeb code section below (code from router.ex
file)
scope "/", HelloWeb do ----(1)
pipe_through :browser
get "/", PageController, :index ---(2)
end
Looking at line (1)
in the code above,
scope
. Howcome there is no parenthesis.HelloWeb
is the name of a module. What is the purpose in adding it hereLooking at line (2)
in the code above,
PageController
. The module PageController
is in is defmodule HelloWeb.PageController do
. My guess is that adding HelloWeb
in line (1)
kind of makes it a shorten form ?:index
mean (there is a function called index
), specifically the :
. Why use the :
. From my limited knowledge on Elixir :
signifies an atom.StackOverflow may not be the best medium for these types of "YMMV" questions, but let me attempt a couple brief explanations.
In some languages you may have heard "everything is an object." In Elixir, it's almost like "everything is a function." Not quite, but thinking that way can help explain things.
scope
isn't a function, it's a macro, but like a function, it can accept arguments. In Elixir, parentheses around arguments are optional. This can help readability -- e.g. even def
used to define a function is actually a thing that accepts arguments.
The 2nd argument (HelloWeb
) allows us to omit the full module names. If you skipped that argument, you would have to list the full module names for your routes, e.g.
get "/", HelloWeb.PageController, :index
So that answers your next question: yes, providing that as an argument allows us to shorten the form.
Next, why is the index
function specified with a :
? You are correct: this indicates an atom. Module and function names are stored internally as atoms. Importantly, when you want to call a function at runtime and you want the exact function to vary (i.e. be a variable), you can use Kernel.apply/3
, which accepts a Module, the function name (as an atom), and a list of arguments. E.g. instead of IO.puts("Hello world")
, you would call apply(IO, :puts, ["Hello world"])
. This syntax is similar to other languages (e.g. something like PHP's call_user_func()
). It's common to see "MFA" notation, which stands for Module Function Arguments, and the function name is always an atom.