Packages in Erlang
Packages are simply namespaces for modules. All old Erlang modules automatically belong to the top level ("empty-string") namespace, and do not need any changes.
The full name of a packaged module is written as e.g.
i.e., as atoms separated by periods,
where the package name is the part up to
but not including the last period;
in this case "
A more concrete example is the module
which is in the
Package names can have any number of segments, as in
The atoms in the name can be quoted, as in
or even the
whole name, as in
'foo.bar.baz' but the concatenation of
periods must not contain two consecutive period characters or
end with a period,
The periods must not be followed by whitespace.
The code loader maps module names onto the file system directory
E.g., the module
erl.lang.term corresponds to a file
in the search path.
Note that the name of the actual object file corresponds to
the last part only of the full module name.
(Thus, old existing modules such as
simply map to
.../lists.beam, exactly as before.)
A packaged module in a file "
foo/bar/fred.erl" is declared
This can be compiled and loaded from the Erlang shell using
your current directory is the same as that of the file.
The object file will be named
The Erlang search path works exactly as before,
except that the package segments will be appended to each
directory in the path in order to find the
file. E.g., assume the path is
["/usr/lib/erl", "/usr/local/lib/otp/legacy/ebin", "/home/barney/erl"].
Then, the code for a module named
foo.bar.fred will be
lists, which is in the top-level package,
will be looked for as
Normally, if a call is made from one module to another, it is assumed that the called module belongs to the same package as the source module. The compiler automatically expands such calls. E.g., in:
-module(foo.bar.m1). -export([f/1]). f(X) -> m2:g(X).
m2:g(X) becomes a call to
If this is not what was intended, the call can be written
explicitly, as in
-module(foo.bar.m1). -export([f/1]). f(X) -> fee.fie.foe.m2:g(X).
Because the called module is given with an explicit package name, no expansion is done in this case.
If a module from another package is used repeatedly in a module, an import declaration can make life easier:
-module(foo.bar.m1). -export([f/1, g/1]). -import(fee.fie.foe.m2). f(X) -> m2:g(X). g(X) -> m2:h(X).
will make the calls to
m2 refer to
More generally, a declaration
will cause calls to
to be expanded to
Old-style function imports work as normal (but full module names must be used); e.g.:
-import(fee.fie.foe.m2, [g/1, h/1]).
however, it is probably better to avoid this form of import altogether in new code, since it makes it hard to see what calls are really "remote".
If it is necessary to call a module in the top-level package
from within a
named package, the module name can be written either with an
initial period as
in e.g. "
.lists", or with an empty initial atom, as in
However, the best way is to use an import declaration -
this is most obvious to
the eye, and makes sure we don't forget adding a period somewhere:
-module(foo.bar.fred). -export([f/1]). -import(lists). f(X) -> lists:reverse(X).
The dot-syntax for module names can be used in any expression. All segments must be constant atoms, and the result must be a well-formed package/module name. E.g.:
spawn(foo.bar.fred, f, [X])
is equivalent to
spawn('foo.bar.fred', f, [X]).
The Erlang Shell
The shell also automatically expands remote calls,
however currently no
expansions are made by default.
The user can change the behaviour by using the
shell command (or its abbreviation
If a new import is made of the same name,
this overrides any previous import.
(It is likely that in the future, some
system packages will be pre-imported.)
In addition, the shell command
(and its alias
imports all modules currently found in the path for a given
package name. E.g.,
assuming the files "
.../foo/bar/bambam.beam" can be found from our current
Note: The compiler does not have an "import all" directive, for the
reason that Erlang has no compile time type checking.
E.g. if the wrong search
path is used at compile time, a call
could be expanded to
without any warning, instead of the intended
foo.bar happens to be found first in the path.
declaring each use of a module makes for safe code.