Elixir Process State
Process state is a value a long-running process carries while it works. A counter process carries its current count from one message to the next.
A fresh counter reads back zero
The counter starts its loop with 0. A read message asks for the count, and the reply carries it back.
defmodule Counter do
def loop(count) do
receive do
:inc -> loop(count + 1)
{:read, sender} ->
send(sender, {:count, count})
loop(count)
end
end
end
counter = spawn(Counter, :loop, [0])
send(counter, {:read, self()})
count =
receive do
{:count, n} -> n
end
IO.puts(count)One :inc raises the count to one
The :inc message is sent before the read message. Send order means the increment is handled first.
defmodule Counter do
def loop(count) do
receive do
:inc -> loop(count + 1)
{:read, sender} ->
send(sender, {:count, count})
loop(count)
end
end
end
counter = spawn(Counter, :loop, [0])
send(counter, :inc)
send(counter, {:read, self()})
count =
receive do
{:count, n} -> n
end
IO.puts(count)State survives between reads
The first read answers 0, then one :inc lands, and the second read answers 1. The count lived inside the counter the whole time.
defmodule Counter do
def loop(count) do
receive do
:inc -> loop(count + 1)
{:read, sender} ->
send(sender, {:count, count})
loop(count)
end
end
end
counter = spawn(Counter, :loop, [0])
send(counter, {:read, self()})
first =
receive do
{:count, n} -> n
end
send(counter, :inc)
send(counter, {:read, self()})
second =
receive do
{:count, n} -> n
end
IO.puts(first)
IO.puts(second)Example
defmodule Counter do
def loop(count) do
receive do
:inc -> loop(count + 1)
{:read, sender} ->
send(sender, {:count, count})
loop(count)
end
end
end
counter = spawn(Counter, :loop, [0])
send(counter, :inc)
send(counter, :inc)
send(counter, {:read, self()})
count =
receive do
{:count, n} -> n
end
IO.puts(count)Key points
- Carrier: the loop function takes the current state as an argument.
- Update: to change state, the loop calls itself with the new value as the argument.
- Read: a read message carries the sender PID so the loop knows where to reply.
- Reply: the loop sends the state back and calls itself with the same state.
- Order: one sender's messages are handled in send order, so a read sent after two :inc messages sees both.
- Private: the state lives inside the process, and outside code reaches it only through messages.
In this example, the counter is spawned with a starting count of 0 and then receives two :inc messages. Each :inc makes the loop call itself with the count plus one. The read is handled last, so the reply is {:count, 2} and the script prints 2.
Note
nothing is changed in place here, because each loop call simply receives the next count as a fresh argument.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
How does the counter move from a count of 1 to a count of 2?