2026-03-24

erlang

My AI generated notes on Erlang for re-learning purposes.

#work-in-progress#erlang#notes#long
model: gpt-oss-20b human: nmcgi

This guide covers all the core topics you'll find on the official Erlang/OTP documentation but in a much shorter, "cheat‑sheet" style. Use it as a quick reference or a refresher before diving into projects.

1. Introduction

  • What is Erlang? A functional, concurrent language created by Ericsson (1986). It runs on the BEAM virtual machine and is the foundation for fault‑tolerant distributed systems.
  • Why learn Erlang?
    • Lightweight processes (spawn) and message passing → massive concurrency.
    • Hot code swapping & zero‑downtime upgrades.
    • Mature OTP framework for building reliable applications.

2. Program Structure

-module(hello).
-export([start/0]).

start() ->
    io:format("Hello, Erlang!~n").
  • -module declares the module name (must match filename).
  • -export lists functions available outside the module.
  • Functions end with a period .; clauses separated by semicolons ;.

3. Syntax Basics

ElementExampleNotes
Comments% this is a commentSingle‑line, starts with %.
Atomsok, 'my atom'Immutable constants; lowercase or quoted.
VariablesX = 42Must start with uppercase or _; single‑assignment.
Semicolonfoo(1) -> a; foo(_) -> b.Separates function clauses.

4. Variables & Data Types

TypeExampleNotes
integer42, -7, 16#FFArbitrary precision; hex with 16#.
float3.14, 1.0e-364‑bit IEEE 754.
atomok, error, trueImmutable named constant.
booleantrue, falseSpecial atoms.
string"hello"List of Unicode code points.
binary<<"hello">>Efficient byte sequence.
list[1, 2, 3]Linked list; head/tail with `[H
tuple{ok, Value}Fixed‑size, heterogeneous.
map#{key => val}Key‑value store (Erlang 17+).

Tip: Use erlang:type_of/1 or pattern matching to inspect types at runtime.

5. Operators

CategorySymbolsExample
Arithmetic+ - * / div remX = A + B, 7 div 23
Assignment=X = 42 (pattern match / bind)
Comparison== /= =:= =/= < > =< >=A =:= B (exact equality)
Logicaland or not andalso orelsetrue andalso false
Bitwisebsl bsr bor band bxor bnot1 bsl 38
List++ --[1,2] ++ [3][1,2,3]

Note: == does type coercion (1 == 1.0 is true); =:= is strict.

6. Booleans

Erlang's only boolean values are the atoms true and false.

Flag = true,
if
    Flag -> io:format("yes~n");
    true -> io:format("no~n")   % 'true' acts as else
end.
  • Use andalso / orelse for short‑circuit evaluation in guards.

7. Conditional Statements

case

case Score of
    S when S >= 90 -> io:format("A~n");
    S when S >= 80 -> io:format("B~n");
    _              -> io:format("C~n")
end.

if

if
    X > 0  -> positive;
    X =:= 0 -> zero;
    true   -> negative
end.
  • Every if branch must match; use true as a catch‑all (like else).
  • case is generally preferred over if for readability.

8. Recursion & Loops

Erlang has no traditional loop constructs — use recursion instead:

print_n(0) -> ok;
print_n(N) when N > 0 ->
    io:format("~p~n", [N]),
    print_n(N - 1).

Tail‑recursive version for large N (stack‑safe):

sum(N) -> sum(N, 0).

sum(0, Acc) -> Acc;
sum(N, Acc) when N > 0 ->
    sum(N - 1, Acc + N).
  • lists:foreach/2 and lists:map/2 replace many imperative loops.
  • break / continue have no equivalent — redesign with recursion or list functions.

9. Lists & Tuples

Nums = [1, 2, 3, 4, 5],
[H | T] = Nums,          % H = 1, T = [2,3,4,5]
io:format("~p~n", [H]).
  • List comprehension: [X * 2 || X <- Nums, X > 2][6, 8, 10].
  • Tuples: Point = {3, 4}, access via pattern match: {X, Y} = Point.
% Common list operations
Doubled = lists:map(fun(X) -> X * 2 end, Nums),
Evens   = lists:filter(fun(X) -> X rem 2 =:= 0 end, Nums),
Sum     = lists:foldl(fun(X, Acc) -> X + Acc end, 0, Nums).

10. Strings & Binaries

  • Strings in Erlang are lists of integers (character codes).
  • Binaries (<<"...">>) are more memory‑efficient for large text.
Str = "Hello",
Bin = <<"Hello">>,
io:format("~s~n", [Str]),
io:format("~s~n", [binary_to_list(Bin)]).

Common operations:

Len    = length("hello"),                  % 5
Upper  = string:to_upper("hello"),         % "HELLO"
Joined = string:join(["a","b","c"], ","),  % "a,b,c"
  • Use the string module (Erlang 20+) for Unicode‑aware string handling.

11. User Input

io:format("Enter your name: "),
{ok, Name} = io:read(""),
io:format("Hello, ~p!~n", [Name]).
  • io:get_line/1 reads a full line as a string (including newline).
  • io:read/1 parses an Erlang term from stdin.

12. Pattern Matching & Guards

Pattern matching is central to Erlang — it replaces most conditionals:

{ok, Value} = get_value().     % crash if not {ok, _}
[H | _]     = some_list().     % bind head, ignore tail

Guards add boolean constraints to patterns:

classify(X) when X > 0  -> positive;
classify(0)              -> zero;
classify(X) when X < 0  -> negative.
  • Guards allow only a safe subset of expressions (no side effects).
  • Multiple guards in one clause: when X > 0, X < 100 (both must hold).

13. Functions & Modules

Declaration

-module(math_utils).
-export([add/2, square/1]).

Definition

add(A, B) -> A + B.

square(X) -> X * X.
  • Functions are identified by Name/Arity (e.g., add/2).
  • Multiple clauses are matched top‑to‑bottom.

Scope

ScopeNotes
Module‑privateNot listed in -export — invisible outside module.
ExportedListed in -export — callable as Module:Fun(Args).

14. Fun Expressions

Anonymous functions (like function pointers or lambdas):

Double = fun(X) -> X * 2 end,
Result = Double(5),               % 10

Apply = fun(F, X) -> F(X) end,
Apply(Double, 7).                 % 14
  • Pass funs as arguments for callbacks and higher‑order functions.
  • Reference named functions with fun Module:Name/Arity.
Sorted = lists:sort(fun(A, B) -> A =< B end, [3,1,2]).

15. Concurrency Primitives

Pid = spawn(fun() -> io:format("Hi~n") end),
Pid ! {self(), hello},
receive
    {From, Msg} ->
        io:format("Got ~p from ~p~n", [Msg, From])
after 1000 ->
    io:format("Timeout~n")
end.
  • spawn/1 or spawn/3 creates a new lightweight process.
  • ! sends a message; receive blocks until a matching message arrives.
  • after Timeout clause handles the no‑message case.
  • link/1 and monitor/2 for fault tolerance between processes.

16. Records

Records are named tuples — Erlang's equivalent of structs:

-record(person, {name, age = 0}).

P = #person{name = "Alice", age = 30},
io:format("~s is ~p~n", [P#person.name, P#person.age]).
  • Defined with -record(Name, Fields) in module or header file.
  • Access fields with Record#record_name.field.
  • Update: P2 = P#person{age = 31} (creates a new record).

17. Error Handling

try
    risky_operation()
catch
    throw:Reason  -> io:format("Thrown: ~p~n", [Reason]);
    error:Reason  -> io:format("Error: ~p~n",  [Reason]);
    exit:Reason   -> io:format("Exit: ~p~n",   [Reason])
after
    cleanup()
end.
  • error:badarg, error:badarith, etc. are standard runtime errors.
  • erlang:error(Reason) raises an error; throw(Reason) for flow control.
TechniqueDescription
Pattern match {ok, V} / {error, R}Idiomatic error propagation.
try/catchException handling.
catch ExprReturns {'EXIT', Reason} on error.
dbg / redbugTracing and debugging.

18. File I/O

ModeSymbol
readOpen for reading.
writeOpen for writing (truncate).
appendOpen for appending.
binaryRead/write raw binaries.
{ok, File} = file:open("data.txt", [read]),
{ok, Line} = file:read_line(File),
io:format("~s", [Line]),
file:close(File).
  • file:read_file(Path) reads entire file into a binary in one call.
  • file:write_file(Path, Data) writes and closes in one call.

19. OTP Basics

OTP (Open Telecom Platform) provides battle‑tested behaviours:

  • gen_server — generic server process.
  • supervisor — manages child processes and restart strategies.
  • application — defines application lifecycle.

Example skeleton of a gen_server:

-behaviour(gen_server).
-export([start_link/0, init/1, handle_call/3, handle_cast/2]).

start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

init([]) -> {ok, #{}}.

handle_call(_Msg, _From, State) ->
    {reply, ok, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

20. Core Standard Modules

ModuleKey FunctionsExample
ioformat/2, get_line/1io:format("~s", ["Hello"])
listsmap/2, filter/2, foldl/3lists:map(fun(X) -> X*2 end, [1,2,3])
mapsput/3, get/2, merge/2maps:get(a, #{a=>1})
stringto_upper/1, join/2, split/2string:to_upper("hi")
fileread_file/1, write_file/2file:read_file("f.txt")
timersleep/1, send_after/3timer:sleep(1000)
etsnew/2, insert/2, lookup/2ets:new(tab, [named_table])

21. Hot Code Swapping

code:load_file(my_module).
  • Allows updating a running module without stopping the VM.
  • Running processes continue on the old version until they call into the module again.
  • OTP behaviours handle version transitions via code_change/3 callbacks.

22. Miscellaneous

  • Macros (-define(NAME, Value).) for constants: ?MODULE, ?LINE.
  • Include files: -include("records.hrl"). to share record definitions.
  • Ports: interface to external C programs or OS processes.
  • NIFs (Native Implemented Functions): embed C code directly in Erlang.
  • Distribution: net_kernel:start/1 to connect BEAM nodes across machines.

23. Quick Reference Cheat Sheet

% Module declaration
-module(foo).
-export([bar/1]).

% Record definition
-record(point, {x = 0, y = 0}).

% Function with pattern matching
bar(0) -> zero;
bar(N) when N > 0 -> positive;
bar(_) -> negative.

% List comprehension
Squares = [X*X || X <- lists:seq(1, 5)].

% Spawn a process and message it
Pid = spawn(fun() ->
    receive
        {From, Msg} -> From ! {self(), Msg}
    end
end),
Pid ! {self(), hello},
receive Reply -> io:format("~p~n", [Reply]) end.

% Error handling
try risky() catch error:R -> io:format("Error: ~p~n", [R]) end.

Final Note

This guide is intentionally terse. For deeper explanations, examples, and exercises, refer to the official Erlang/OTP documentation or books like Programming Erlang by Joe Armstrong. Happy coding!