Why do Erlang modules look like atoms in Elixir?
This is a post about how Elixir knows the difference between Erlang modules, Elixir modules, and Elixir atoms
If you have ever come across Elixir code that calls an Erlang module, you will know it looks something like this:
However, normal atoms that are declared in Elixir code don’t get functions, so how does Elixir know the difference between them?
If we open up
IEx and create some atoms, there appears to be no difference between the
:os atom and the
:tyler atom. Yet when we try to call the
system_time/0 function on the
:os atom it works, but trying to call any kind of function on the
:tyler atom raises an error because there is no
So how does Elixir know when we are dealing with an atom and when we are dealing with an Erlang module?
There are a whole bunch of IEx helpers that are useful for exploring these kinds of things, and the one that will help us right now is the i/1 function, which will print information about the data type of the value we pass it.
So lets test that out on the
:tyler atom and the
:os atom. Starting with the
:tyler atom, we can see we get some information about its value:
If we do the same for the
:os atom we get a lot more information, and its easy to see that Elixir knows that we are now dealing with a module and not just a regular atom:
If you compare the
Reference modules fields for each, you can see that
:tyler is just an
Module, Atom. This is not surprising; we already said that
:os is an atom and a module, while
:tyler is just a regular atom.
Lets try the same thing for the
String Elixir module:
Obviously we know that
String is a module, so we are not surprised to see the module-related stuff in there that looks similar to the previous example with
:os. What is interesting here is the
Reference modules still says
If we look back at the screenshot above, we can see that the
Raw representation field event tells exactly how the module name is represented as an atom in Elixir. Lets play around with that:
Neat! This demonstrates that
:"Elixir.String" are equivalent! If you define a module in your code by doing
defmodule MyModule or
defmodule Foo.Bar then you would be able to access it in the same way,
By the way: the reason you need the quotes
:"Elixir.String" atom is because without them the dot
. would be ambigious. You need to use quotes when creating an atom that has any special characters.
This also shows that Elixir keeps track of Erlang vs Elixir modules by using the
Elixir prefix in the module name (you can scroll back up and see that was not present for
:os). In fact, all Pascal-case “names” Elixir are just syntactic sugar for
Wrapping up, the key take aways are that:
- All modules are atoms (
- Not all atoms are modules (
- Erlang and Elixir modules are differentiated by the
Elixirprefix that is present for