Erlang basics: what the language is and where it is used

What Erlang is

Erlang is a functional programming language built for systems that must not stop. Ericsson designed it in the 1980s for telephone switches, where a failed call must not take the exchange down, and that requirement still shapes the language.

Programs run on the BEAM virtual machine. A BEAM node holds millions of lightweight processes that share nothing and talk by messages, and a supervisor restarts the processes that crash. The standard library and the OTP framework turn those two ideas into the pattern behind every Erlang backend you meet in production.

Install Erlang and check the version

Every installation is the same runtime, one Erlang/OTP release. Install it from the package manager of your system: APT on Ubuntu, EPEL with DNF on Linux distributions that follow RHEL, Homebrew on macOS, pkg on FreeBSD, Chocolatey or Winget on Windows 11. The install pages carry the exact commands for each system.

Docker needs no install at all: the Erlang in Docker page runs the official image.

The version check is the same everywhere. Ask the shell for its version:

erl -version

Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version 15.2.7.14

The emulator version follows the OTP release. Ask for the release number itself:

erl -noshell -eval 'io:format("~s~n", [erlang:system_info(otp_release)]), halt().'

27

Both answers were measured on Erlang/OTP 27 on Alpine Linux 3.24 (x86_64). A newer OTP release prints its own numbers.

The first module

Every Erlang program is a module: one .erl file whose header names the module and whose export list names the functions that other modules may call. Save this as hello.erl.

-module(hello). -export([main/0]). main() -> io:format("Hello, Erlang!~n").

Compile it with erlc, which writes hello.beam, the bytecode the runtime loads. Then call the function and stop the node:

erlc hello.erl
erl -noshell -eval 'hello:main(), halt().'

Hello, Erlang!

The header is not ceremony. The name after -module must equal the file name without .erl, so erlc rejects a hello.erl that declares another module, and the arity in the export list is the argument count: main/0 is main with no arguments.

The shell

The erl program is also an interactive shell. Start it with no arguments, type an expression, and end the line with a period.

erl

1> 2 + 3.
5
2> hello.
hello
3> [1, 2, 3] ++ [4].
[1,2,3,4]

The shell prints the value of every expression. Arithmetic returns a number, an atom prints as itself, and a list prints as its elements inside brackets. None of the three needs a module or a compile step, which makes the shell the fastest way to test an idea.

Type q(). to leave the shell. Lesson 3 covers the helpers: b() lists the current bindings, h() the history, and v(N) recalls an earlier result.

Three examples

Three short programs show what the language is built around: recursion instead of loops, pattern matching instead of casts, and guards instead of nested conditions.

Recursion over a list

Erlang has no loop statement. A list is a head and a tail, and a recursive function walks it until the tail is empty. Save this as total.erl.

-module(total). -export([sum/1]). sum([]) -> 0; sum([Head | Tail]) -> Head + sum(Tail).

Compile the module and add the numbers of a list:

erlc total.erl
erl -noshell -eval 'io:format("~p~n", [total:sum([1, 2, 3, 4])]), halt().'

10

Pattern matching

The = sign is not an assignment: it matches the right side against the pattern on the left. A pattern with an unbound variable binds it, and a pattern that does not fit fails at once. In the shell:

erl

1> {ok, Value} = {ok, 42}.
{ok,42}
2> Value.
42
3> [Head | Tail] = [1, 2, 3].
[1,2,3]
4> Head.
1
5> Tail.
[2,3]

The tuple and the list split into their parts in one step, with no index and no cast. The same mechanism picks the arguments of a function, which is how most Erlang code is written.

Guards

A guard is the test after the when keyword. When several clauses of a function match, the guards decide which one runs. Save this as classify.erl.

-module(classify). -export([number/1]). number(N) when N > 0 -> positive; number(0) -> zero; number(_) -> negative.

Compile it and classify three numbers:

erlc classify.erl
erl -noshell -eval 'io:format("~p ~p ~p~n", [classify:number(7), classify:number(0), classify:number(-3)]), halt().'

positive zero negative

The course

The Erlang course goes on for fifty lessons: types, recursion, pattern matching, EUnit, GenServer, supervisors, distributed nodes, and two capstone projects.

Start with lesson 1, What is Erlang and where it runs, and follow the chain of previous and next links at the bottom of every page.

The code on this page was run with Erlang/OTP 27 on Alpine Linux 3.24 (x86_64).

Article author: Arthur Isaev

Banner image