Lessons

Every module combines a model, a rule, an example, and a challenge.

That is how understanding replaces memorization.

Feedback Loop

Make progress visible while you learn.

The page now rewards effort, not just perfect answers. Write notes, solve drills, and build momentum.

XP

0 XP

Start with one lesson note or one code drill to unlock your first progress signal.

FOCUS

Best next move

Open a module, write one thought in the note field, then run one coding drill.

PRACTICE

0 notes, 0 drills

0 quiz wins and 0 checked milestones completed.

Lessons

Every module combines a model, a rule, an example, and a challenge.

That is how understanding replaces memorization.

Module 1

Syntax and data types

Lesson 1: Atoms, numbers, strings

Erlang clearly separates atoms like ok, numbers like 42, and binaries like <<"hi">>.

Memory line: An atom often describes meaning, a binary often carries actual data.

State = idle,
Count = 3,
Name = <<"Ada">>.

Lesson 2: Pattern matching

Pattern matching is not just comparison. It is structured unpacking of values.

Memory line: Erlang always asks, Does the shape fit?

{ok, User} = {ok, #{name => <<"Ada">>}}.
Mini challenge

Which parts of {error, timeout} can you extract directly with pattern matching?

Practice lab

Module 2

Functions, guards, and recursion

Lesson 3: Multiple function heads

A function can have multiple shapes. Erlang checks them from top to bottom.

Memory line: First pattern, then guard, then function body.

size([]) -> 0;
size([_ | Tail]) -> 1 + size(Tail).

Lesson 4: Guards

Guards make rules readable and keep logic out of the body when possible.

Memory line: Guards clarify cases before work begins.

kind(N) when N > 0 -> positive;
kind(0) -> zero;
kind(_) -> negative.

Lesson 5: Recursion instead of loops

In Erlang, recursion is the normal way to move through data.

Memory line: Every recursion needs a start, a step, and an end.

sum([]) -> 0;
sum([H | T]) -> H + sum(T).
Mini challenge

Mentally design a function all_even/1 that returns true only if every element is even.

Practice lab

Module 3

Processes and message passing

Lesson 6: Starting processes

An Erlang process is extremely lightweight and owns its own state.

Memory line: Do not share state, send messages.

Pid = spawn(fun loop/0).

Lesson 7: Sending messages

With !, you send messages asynchronously into a process mailbox.

Memory line: Sending is immediate, processing comes later.

Pid ! {self(), ping}.

Lesson 8: Receive loops

A process is often modeled as a loop: receive a message, react, continue.

Memory line: Behavior emerges from receiving plus the next loop.

receive
    stop -> ok;
    Msg -> io:format("~p~n", [Msg]), loop()
end.
Mini challenge

How would you design a counter process that reacts to increment and get?

Practice lab

Module 4

OTP and fault tolerance

Lesson 9: Let it crash

In Erlang, error handling is often structural: one process may crash while another restores it.

Memory line: Not every error should be fixed inside the same process.

link(WorkerPid).

Lesson 10: GenServer thinking

GenServer encapsulates state and standardizes the message flow.

Memory line: OTP gives you structure for repeating process patterns.

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

Lesson 11: Supervisors

Supervisors decide whether a single worker or an entire group should restart.

Memory line: Resilience is a tree structure, not an accident.

{one_for_one, 5, 10}
Mini challenge

When would a one_for_one strategy make more sense than one_for_all?

Practice lab

Module 5

Concurrency patterns

Lesson 12: Worker pools

Multiple processes can handle the same kind of task in parallel without blocking one another.

Memory line: Parallelism needs work distribution, not just more CPU.

Workers = [spawn(fun worker/0) || _ <- lists:seq(1, 4)].

Lesson 13: Isolating state

State should ideally live inside a single process and never be shared directly.

Memory line: Isolation reduces side effects.

store_loop(State) ->
    receive
        {put, Key, Val} -> store_loop(maps:put(Key, Val, State));
        {get, From, Key} -> From ! maps:get(Key, State), store_loop(State)
    end.
Mini challenge

Sketch a three-step pipeline with one process for receiving, one for validating, and one for storing.

Practice lab

Module 6

Distributed Erlang

Lesson 14: Nodes

A node is a running Erlang instance that can cooperate with other nodes.

Memory line: Distribution starts with explicit connection, not magic.

net_kernel:connect_node('worker@host').

Lesson 15: Remote messaging

Messages can cross nodes as long as naming and connectivity are correct.

Memory line: A distributed system is only as good as its failure assumptions.

{service, 'worker@host'} ! ping.

Lesson 16: Production thinking

In distributed systems, timeouts, retries, monitoring, and ownership matter.

Memory line: Strong systems plan for network failure from the start.

receive
    reply -> ok
after 2000 ->
    timeout
end.
Mini challenge

What kinds of failures can happen when a remote node is temporarily unreachable?

Practice lab

Practice Studio

Write Erlang yourself and get instant feedback.

These drills are lightweight browser checks, not a full compiler, but they push learners into active construction instead of only reading.

Drill 1

Pattern Match a Success Tuple

Write one Erlang line that extracts User from a value shaped like {ok, #{name => <<"Ada">>}}.

No feedback yet.

Drill 2

Recursive Sum Function

Write a recursive sum/1 function with a base case for [] and a recursive step for [H | T].

No feedback yet.

Drill 3

Mailbox Counter Loop

Sketch a process loop that handles an increment message and a get message that replies back to From.

No feedback yet.

Account

Login, register, and save your progress.

Account

Login, register, and save your progress.