How does keeping state in Elixir work?
Tags: elixir, state, functional
Published: 2019-10-05 08:28:24

---
title: How does keeping state in Elixir work?
published: true
tags: elixir, state, functional programming
canonical_url: 
---

In 2011, when I was new to Erlang and functional programming, the biggest question I had was something like this:

> When there is no state in functional programming, how do you store, retrieve and update state?”

I read about [gen\_server](http://erlang.org/doc/man/gen_server.html) that really just was the point where I realised that although everyone kept saying “There is no state in functional programming” you actually do have mechanisms to store state in Erlang/Elixir for later use.

So I dived into it and learned how it’s done.

## How it’s done

Actually the concept behind it is not so much rocket-science. Basically it consists of a function calling itself recursively and communicating with other processes which want to store and update the state. If the state needs to be changed, the next call will be made with the new state.

Let’s build a Stack module that holds it’s values and allows users to `push` and `pop` values from it.

We start off with a simple function that will run and keep the state by recursively calling itself and receiving basic messages to handle changes to the state:

```elixir
defmodule Stack do
  def loop(state) do
    receive do
      {_from, :push, value} ->
        loop([value | state])

      {from, :pop} ->
        [h | t] = state
        send(from, {:reply, h})
        loop(t)
    end

    loop(state)
  end
end
```

`loop/1` waits for new messages to arrive and uses `receive` to block until there are messages for this process which will be pattern-machted against. As you can see, there are two patterns for the two operations we support currently.

The first one will match `{_from, :push, value}` which handles pushes on to the stack. The sending pid `_from` is not needed as this is an asynchronous operation. It starts the next iteration with the new `value` added as the new first element of `state` which will again wait for new messages to arrive.

The other pattern `{from, :pop}` handles the pop operation. The message sender `from` will receive back a message with the first element of `state` extracted while the rest of the list is given to yet another call to `loop/1` which will then wait for another message to arrive.

# Test it

Let’s take our stack implementation for a spin. Start `iex`, paste the above module into it and we are ready to go! To start the stack, just spawn the function as a process:

```elixir
iex> pid = spawn(Stack, :loop, [[]])
#PID<0.108.0>
```

`spawn/3` expects a module (Stack), the function name as an atom (:loop) and a list of arguments, which in our case is an empty list. This makes the initial call, which is essentially `Stack.loop([])`. The returned `pid` is a process identifier to which all messages need to be sent.

To push a new value on to the stack, we need to send that `pid` a message like this:

```elixir
iex> send(pid, {self(), :push, 1})
{#PID<0.88.0>, :push, 1}
```

`self()` returns the value of the current process (which is iex’s `pid` in our case) and send will return the message sent. For this operation we don’t need it, but it’s a good practice to send it anyway. Also we don’t see any change to the stack yet, but remember: the push operation is async.

Now let’s see the change in the stack by popping a value from the stack:

```elixir
iex> send(pid, {self(), :pop})
{#PID<0.88.0>, :push, 1}
```

Here, `self()` is required, because we expect a message back to our iex-pid containing the value. Again, `send` returns the message sent and nothing else happens. That’s because we didn’t read the message we got back yet. Let’s use the iex helper `flush` to retrieve the contents of our main process’ mailbox:

```elixir
iex> flush
{:reply, 1}
:ok
```

And there it is; as expected, the stack contained the value `1`.

# a clean client interface

As our stack is now working, we should build a nice, clean API around it. A user that would want to use the stack module should not care about which messages are required to sent to the process. Instead he/she should use only functions to place values on the stack:

Let’s extend the module and add a bunch of short functions that build up the API and a clean client user interface.

```elixir
defmodule Stack do
    ...

    def start_link(state) do
        spawn_link( __MODULE__ , :loop, [init(state)])
    end

    def init(state), do: state

    def push(pid, value) do
        send(pid, {self(), :push, value})
        :ok
    end

    def pop(pid) do
        send(pid, {self(), :pop})

        receive do
            {:reply, value} -> value
        end
    end
end
```

If you compare this against the callbacks that you would need to implement when using [GenServer](https://hexdocs.pm/elixir/GenServer.html), then you will see that it uses the same naming and function signatures. This is not by accident - it is to show you that GenServer does exactly the same as the above code. Except for a little more error handling and in a more generic way of course. But the concepts remain the same.

Btw. thanks to [tail call optimization](http://learnyousomeerlang.com/recursion) the call stack of the `loop/1` function is constant in terms of memory usage and therefor not a problem when running forever and ever.

Here I will leave you off to some experimenting with state as messages and recursive functions. Happy Elixir’ing!