Elixir modules are generally named with a hierarchical structure separated by dots:
defmodule MyProject.Thing do
# ...
end
This is just a convention and provides no special functionality. Like Erlang
modules, Elixir modules are just atoms,
prefixed with "Elixir."
:
Atom.to_string(List) # "Elixir.List"
:"Elixir.List" # List
Atom.to_string(MyProject.Thing) # "Elixir.MyProject.Thing"
You can reference an Elixir module by its full name but that’s rather verbose and repetitive, especially in its own implementation. Here’s an example with an Elixir struct and a function that manipulate it:
defmodule MyProject.Thing do
defstruct [:name, value: 0]
def awesome(%MyProject.Thing{name: name} = thing) do
%MyProject.Thing{thing | name: "Awesome #{name}"}
end
end
Using __MODULE__
One way to avoid the repetition of the module name is to use the __MODULE__/0
macro from Kernel.SpecialForms
. It returns the current
module name as an atom:
defmodule MyProject.Thing do
defstruct [:name, value: 0]
def awesome(%__MODULE__{name: name} = thing) do
%__MODULE__{thing | name: "Awesome #{name}"}
end
end
Although the module name is no longer repeated, this may not be the most readable version.
Using an alias
Another way to avoid too much repetition is to use an alias:
defmodule MyProject.Thing do
defstruct [:name, value: 0]
alias MyProject.Thing, as: Thing
def awesome(%Thing{name: name} = thing) do
%Thing{thing | name: "Awesome #{name}"}
end
end
This is a bit more readable.
Since aliases are often used as shortcuts for the last part of the module name like this, it is the default behavior if you don’t specify a name:
# These two aliases are equivalent:
alias MyProject.Thing
alias MyProject.Thing, as: Thing
You can also alias an Elixir module to whatever name you want if you prefer:
alias MyProject.Thing, as: Foo
Making a module alias itself
Ok, so an alias is good, but the solution above still makes you repeat the full
module name twice. However, you can combine it with __MODULE__
and get the
best of both worlds:
defmodule MyProject.Thing do
defstruct [:name, value: 0]
alias __MODULE__
def awesome(%Thing{name: name} = thing) do
%Thing{thing | name: "Awesome #{name}"}
end
end
This way you both avoid the repetition of the full name and can use the more
readable Thing
instead of __MODULE__
in the rest of the code.
Credits
I learned this while reading chapter 2 of Functional Web Development with Elixir, OTP, and Phoenix, Rethink the Modern Web App by Lance Halvorsen.