---
title: "Exploring Elixir processes"
description: "Expanding on our FizzBuzz example from the previous post."
canonical: https://oozou.com/blog/exploring-elixir-processes-18
locale: en
date: 2014-12-16
author: "OOZOU Team"
---

# Exploring Elixir processes

> Expanding on our FizzBuzz example from the previous post.

Published: 2014-12-16 · Author: OOZOU Team (Engineering) · 4 min read

Almost 3 months have passed since the release of Elixir 1.0, but we are still very [excited about the language](https://oozou.com/blog/why-we-are-excited-about-elixir-13).

In this blog post we’ll expand on the FizzBuzz example from the previous post, which we’ll now turn into a server.

**The FizzBuzz server**

```
defmodule FizzBuzz do
  @moduledoc "A very simple FizzBuzz server"

  @doc """
    Computes and outputs the FizzBuzz value for the
    provided argument.
  """
  @spec compute(Integer) :: :ok
  def compute do
    receive do
      n -> IO.puts "#{n}: #{compute(n)}"
    end
    compute
  end

  defp compute(n) do
    case {rem(n, 3), rem(n, 5)} do
      {0, 0} -> :FizzBuzz
      {0, _} -> :Fizz
      {_, 0} -> :Buzz
      _      -> n
    end
  end
end
lang-elixir
```

This is a simple module, with some documentation and a [typespec](http://elixir-lang.org/docs/stable/elixir/Kernel.Typespec.html) for compute/0, which works as the main entry point for the FizzBuzz module. It uses [receive/1](http://elixir-lang.org/docs/stable/elixir/Kernel.SpecialForms.html#receive/1) to get the next number from the process’ mailbox, computes (via the private compute/1 function) and outputs the result, before calling itself again to wait for the next message.

**Communicating with the server**

To use our newly created server, we first start it with [spawn/3](http://elixir-lang.org/docs/stable/elixir/Kernel.html#spawn/3), which expects a module name, the name of the function to be called as well as that function’s arguments. It returns the pid of the newly created [process](http://elixir-lang.org/getting_started/11.html), which is stored in the variable fb (remember that parenthesis around function arguments are optional in Elixir).

```
fb = spawn FizzBuzz, :compute, []
lang-elixir
```

We then can use [send/2](http://elixir-lang.org/docs/stable/elixir/Kernel.html#send/2) to send a message to the server:

```
send fb, 3
lang-elixir
```

This will print “3: Fizz” and return 3. Now let’s send several messages to make sure the recursive call in compute/0 works as expected:

```
10..15 |> Enum.map(&send(fb, &1))
lang-elixir
```

Here we use Elixir’s pipe operator ([|>/2](http://elixir-lang.org/docs/stable/elixir/Kernel.html#|>/2)) to send the [Range](http://elixir-lang.org/docs/stable/elixir/Range) of numbers from 10 to 15 into [Enum.map/2](http://elixir-lang.org/docs/stable/elixir/Enum.html#map/2), which uses a partially applied version of send/2 with an anonymous argument (&1). The output is as expected:

```
10: Buzz
11: 11
12: Fizz
13: 13
14: 14
15: FizzBuzz
lang-elixir
```

**Dealing with errors**

At this point the more observant readers may wonder what happens if instead of an integer, we send some other data type to FizzBuzz.compute/0. Let’s try:

```
send fb, 1.0
lang-elixir
```

This leads to the following error message:

```
14:25:32.742 [error] Error in process <0.95.0> with exit value: {badarith,[{'Elixir.FizzBuzz',compute,1,[{file,"fizzbuzz.ex"},{line,10}]},{'Elixir.FizzBuzz',compute,0,[{file,"fizzbuzz.ex"},{line,4}]}]}
lang-elixir
```

This means that the FizzBuzz server crashed. However, since we were dealing with an unlinked process, our main program (in this specific case an iex session) is unaffected by this. Now let’s start the server again, but this time as a [linked process](http://elixir-lang.org/getting_started/11.html#11.3-links) using [spawn_link/3](http://elixir-lang.org/docs/stable/elixir/Kernel.html#spawn_link/3):

```
fb = spawn_link FizzBuzz, :compute, []
lang-elixir
```

Now a problems in our FizzBuzz server will bubble up and also terminate the main process:

```
14:33:40.426 [error] Error in process <0.119.0> with exit value: {badarith,[{'Elixir.FizzBuzz',compute,1,[{file,"fizzbuzz.ex"},{line,10}]},{'Elixir.FizzBuzz',compute,0,[{file,"fizzbuzz.ex"},{line,4}]}]}

** (EXIT from #PID<0.116.0>) an exception was raised:
** (ArithmeticError) bad argument in arithmetic expression
fizzbuzz.ex:10: FizzBuzz.compute/1
fizzbuzz.ex:4: FizzBuzz.compute/0
lang-elixir
```

This could be rectified by adding a guard clause to compute/0 in our FizzBuzz model like this:

```
def compute do
  receive do
    n when is_integer(n) -> IO.puts "#{n}: #{compute(n)}"
    _ -> IO.puts "Invalid argument"
  end
  compute
end
lang-elixir
```

While this works, it goes against one of Erlang’s most important principles, “let it crash”. Instead of programming defensively, errors will just terminate a process and leave it up to monitoring processes (if there are any) to deal with this situation.

**Monitoring**

One way to deal with the above is to set up a monitor. Unlike a link this is a unidirectional relationship between processes. To create a monitor, we start the FizzBuzz server with [spawn_monitor/3](http://elixir-lang.org/docs/stable/elixir/Kernel.html#spawn_monitor/3), which on top of the pid will also return a monitoring reference. We are not using this reference in the following example, but it’s useful for manually disabling monitoring with a call to [demonitor/2](http://elixir-lang.org/docs/stable/elixir/Process.html#demonitor/2).

Now in case the server dies, a message will be sent to the monitoring process:

```
{fb, ref} = spawn_monitor FizzBuzz, :compute, []
send fb, 1.0
lang-elixir
```

Since we didn’t use receive/1 to set up a message receiver in our iex session, we will have to manually call the [flush/0](http://elixir-lang.org/docs/master/iex/IEx.Helpers.html#flush/0) helper to see the monitoring alert:

```
{:DOWN, #Reference<0.0.0.262>, :process, #PID<0.79.0>,
  {:badarith,
    [{FizzBuzz, :compute, 1, [file: 'fizzbuzz.ex', line: 16]},
    {FizzBuzz, :compute, 0, [file: 'fizzbuzz.ex', line: 10]}]}}
lang-elixir
```

**What’s next?**

Dealing with processes in Elixir is very easy. However, by implementing the FizzBuzz server from scratch, we are not making full use of the power that the Erlang/OTP underpinnings provide to Elixir. So in the next installment of this series we’ll revisit the FizzBuzz server, but this time making use of the [gen_server](http://www.erlang.org/doc/man/gen_server.html) and [supervisor](http://www.erlang.org/doc/man/supervisor.html) OTP behaviors. Stay tuned!

---

Contact OOZOU: hello@oozou.com · +66 2544 0000 · https://oozou.com/contact

More for AI agents: https://oozou.com/llms.txt · every page has a markdown twin at its URL plus ".md"
