Building Erlang 22.0 on Debian/Ubuntu

Every time I switch to a new system and have to build a new release of Erlang with kerl I sit and scratch my head to remember which dependencies are required. Once you’re set up or have a prep script it is just too easy to forget which thing is needed for what over the next few years.

Here is my list of pre-build package installs on Ubuntu 18.04 — note that they are in three groups instead of just being a single long apt install command (why apt couldn’t manage to install these all at once is beyond me…):

Group1:

  • gcc
  • curl

Group2:

  • g++
  • dpkg-dev

Group 3:

  • build-essential
  • automake
  • autoconf
  • libncurses5-dev
  • libssl-dev
  • flex
  • xsltproc
  • libwxgtk3.0-dev

Permalink

Better domain modeling in Elixir with sum types

Too often, I use structs and maps exclusively to model domains in Elixir. You might do so too. I think the habit comes from modeling domains in object-oriented languages and from having a one-to-one mapping between structs and database records. But lately, I have found sum types to be a powerful domain modeling technique that can help rid projects of bugs caused by invalid states.

Let’s look at an example.

The problem

Some errors in our applications are caused by invalid state – state we thought impossible in our application but which is nevertheless present when we find a bug.

Suppose we are modeling a chess game:

defmodule Game do
  defstruct [:status, :players, :winning_player]

  @type status :: :not_started | :in_progress | :finished

  @type t :: %__MODULE__{
    status: status(),
    players: {Player.t(), Player.t()} | nil,
    winning_player: Player.t() | nil
  }
end

We have a Game struct with three fields:

  • The status field has three valid values: :not_started, :in_progress, and :finished.

  • We have a tuple representing the two players, along with the possibility of nil if the game has not started.

  • And we have a field for the winning_player when the game finishes, which will be nil otherwise.

Elsewhere, we have a function that determines the message to be displayed at the top of a player’s screen:

def status_message(game) do
  case game.status do
    :not_started ->
      "Waiting for players to join..."

    :in_progress ->
      {player1, player2} = game.players
      "Game on: #{player1.username} vs #{player2.username}."

    :finished ->
      "Player #{game.winning_player.username} wins!"
  end
end

One day we receive a bug report saying that when two users finished the game, they got a 500 error. Looking at our error tracking, we see the exception ** (UndefinedFunctionError) function nil.username/0 is undefined. Looking at the game state, we find this:

%Game{
  status: :finished,
  players: {%Player{username: "gandalf"}, %Player{username: "aragorn"}},
  winning_player: nil
}

“But that’s impossible!” we say. Somehow the game is :finished without a winning_player.

Another day our error tracker alerts us to an exception: ** (MatchError) no match of right hand side value: nil. Then we get a report saying that two players cannot start a game. Looking at the game state, we find the following:

%Game{
  status: :in_progress,
  players: nil,
  winning_player: nil
}

Somehow the game is :in_progress, but the players are not assigned. So the code {player1, player2} = game.players in the status_message/1 function is throwing a match error.

What can be done? Should we pattern match on more fields?

def status_message(game) do
  case {game.status, game.players, game.winning_player} do
    {:not_started, _, _} ->
      "Waiting for players to join..."

    {:in_progress, players, _} when not is_nil(players) ->
      {player1, player2} = players
      "Game on: #{player1.username} vs #{player2.username}."

    {:finished, _, winning_player} when not is_nil(winning_player) ->
      "Player #{winning_player.username} wins!"

    _ ->
      ""
  end
end

No. There is too much defensive programming, and we have a strange catch-all clause at the end that returns an empty message. Those seem like code smells. After all, we know that a finished game should have a winning player. And we know that a game in progress should have two players. That is the business logic of our chess game. The states we’re seeing are invalid, so let’s represent them differently.

Using sum types

Restructuring :finished

Let us first restructure the case when the game is finished. We know a winning player is only present if the game finishes, so let’s enrich the status to use a tagged tuple for the finished case. The tag :finished will continue to mark the finished status, but the second element of the tuple will now hold the winning player struct:

@type status :: :not_started | :in_progress | {:finished, Player.t()}

Now let’s remove the winning_player from the Game struct:

defmodule Game do
  defstruct [:status, :players]

  @type status :: :not_started | :in_progress | {:finished, Player.t()}

  @type t :: %__MODULE__{
    status: status(),
    players: {Player.t(), Player.t()} | nil
  }
end

And we can improve our status_message/1 function:

def status_message(game) do
  case game.status do
    :not_started ->
      "Waiting for players to join..."

    :in_progress ->
      {player1, player2} = game.players
      "Game on: #{player1.username} vs #{player2.username}."


-    :finished ->
-      "Player #{game.winning_player.username} wins!"
+    {:finished, winning_player} ->
+      "Player #{winning_player.username} wins!"
  end
end

Restructuring :in_progress

Now let’s turn :in_progress into another tagged tuple, where the second element holds the two player structs:

@type players :: {Player.t(), Player.t()}
@type status :: :not_started | {:in_progress, players()} | {:finished, Player.t()}

We can now remove the players field from the Game struct:

defmodule Game do
  defstruct [:status]

  @type players :: {Player.t(), Player.t()}
  @type status :: :not_started | {:in_progress, players()} | {:finished, Player.t()}

  @type t :: %__MODULE__{status: status()}
end

Finally, let’s improve our status_message/1 function again:

def status_message(game) do
  case game.status do
    :not_started ->
      "Waiting for players to join..."


-    :in_progress ->
-      {player1, player2} = game.players
+    {:in_progress, {player1, player2}} ->
      "Game on: #{player1.username} vs #{player2.username}."

    {:finished, winning_player} ->
      "Player #{winning_player.username} wins!"
  end
end

By making our status field a sum type, we have modeled our domain more accurately and removed several invalid states that were causing bugs. Take a look at our final status_message/1 function:

def status_message(game) do
  case game.status do
    :not_started ->
      "Waiting for players to join..."

    {:in_progress, {player1, player2}} ->
      "Game on: #{player1.username} vs #{player2.username}."

    {:finished, winning_player} ->
      "Player #{winning_player.username} wins!"
  end
end

Theoretical explanation

Both product types and sum types are called algebraic data types – structs falling under the umbrella of product types. So the set of all possible values for a struct is the cartesian product of the values of its fields.

In practice that means that a struct could contain any combination of each of the possible values of each of its fields. So in order to enumerate all the possible values of our original Game struct, we have to look at all possible combinations of its fields:

# not started
%Game{status: :not_started, players: nil, winning_player: nil}
%Game{status: :not_started, players: {player1, player2}, winning_player: nil}
%Game{status: :not_started, players: {player1, player2}, winning_player: player}
%Game{status: :not_started, players: nil, winning_player: player1}

# in progress
%Game{status: :in_progress, players: nil, winning_player: nil}
%Game{status: :in_progress, players: {player1, player2}, winning_player: nil}
%Game{status: :in_progress, players: {player1, player2}, winning_player: player}
%Game{status: :in_progress, players: nil, winning_player: player}

# finished
%Game{status: :finished, players: nil, winning_player: nil}
%Game{status: :finished, players: {player1, player2}, winning_player: nil}
%Game{status: :finished, players: {player1, player2}, winning_player: player}
%Game{status: :finished, players: nil, winning_player: player}

Sum types are also algebraic data types. But the set of all possible values of a sum type is the disjoint union of all of its variants. In practice that means that our final Game struct, with its restructured status, could only be one of the following:

%Game{status: :not_started}

# OR

%Game{status: {:in_progress, {player1, player2}}

# OR

%Game{status: {:finished, winning_player}}

Using a sum type to model our domain reduced the number of potential (and invalid) states considerably!

Parting thoughts

If you find the idea that domain modeling can remove certain invalid states interesting, you might enjoy seeing the same concept applied in other languages. Richard Feldman gave a great talk about it in Elm. Scott Wlaschin showed the concept in F#. And Yaron Minsky, who coined the term “make illegal states unrepresentable”, explained the concept in OCaml.

Permalink

Erlang: R22.0 doc Mirror Updated

The Erlang doc mirror linked here has been updated to include the R22.0 docs.

Note that some of the internal links and labels say “ERTS-10.4” and “Version 10.4” instead of “ERTS-11.0” and “Version 11.0”. This is an error. The docs refer to ERTS 11.0 but that detail seems to not have been updated when these docs were generated (whoops!). I was looking at fixing that throughout the docs and links, but it turns out to be a lot more complicated than I’m willing to deal with because of the number of references that include the string “10.4” (and some of them are in PDFs and other things more annoying to update than HTML pages). When the R22.1 docs come out that will probably be fixed and I’ll update to avoid confusion in the distant future.

Permalink

An Unprecedented Subtraction

Let’s go back to the origins of this blog with a bit of unexpected code behavior. This time, let’s try removing elements from a list…

Maxwell Smart — because I couldn’t find any proper image for this article

Let’s Subtract!

The beauty of this trick is that the code examples work in both Erlang and Elixir, with barely any changes at all… I’ll do it in Elixir, feel free to try them out in Erlang or efene if you like.

Now, this is a list…

iex(1)> [1, 2, 3]
[1, 2, 3]

And now, we can subtract a few elements from it…

iex(2)> [1, 2, 3] -- [1, 2]
[3]

Let’s now subtract that last one, too…

iex(3)> [1, 2, 3] -- [1, 2] -- [3]
[3]
Santa Clarita Diet — Confusing, I know

What’s going on here?

As usual, it’s better if you first try to decipher the mystery on your own. So, go ahead, check the docs…

Have you found it? Do you know what’s happening?

To be fair, if you’re an Elixir dev you’re in a slightly better situation than your Erlang counterparts: The documentation is, I believe, much clearer.

But, let’s go step by step. First, let’s see what happens if we add parentheses to our expression…

iex(6)> ([1, 2, 3] -- [1, 2]) -- [3]
[]
iex(7)> [1, 2, 3] -- ([1, 2] -- [3])
[3]

That actually makes sense! It looks like -- associates from right to left. Let’s see if we can find documentation that proves it.

In Elixir

What we’re looking for is operator associativity. And elixir actually has a whole page in the docs dedicated to it. There you can see that all binary (as in “with two arguments”) list operations (++ -- .. and <>) associate from Right to Left.

That was easy.

As an aside: Let’s try to verify one if .. is actually right associative…

iex(7)> 1 .. 10
1..10
iex(8)> 1 .. 10 .. 20
** (ArgumentError) ranges (first..last) expect both sides to be integers, got: 1..10..20
(elixir) lib/range.ex:55: Range.new/2

In Erlang

Now let’s try to find that same thing in Erlang… 🕵️‍♀️

Well… There is no page for operator associativity, but if you google carefully you’ll be redirected to the docs for Erlang expressions. There, deep down, in the last part of that page, you’ll find a table dedicated to operator precedence

Table 8.6: Operator Precedence

If you squint a bit, you’ll find ++ and -- there and then you’ll see that they’re both Right associative. Just like =! …

Wait… what?

What’s =!? I’ve never seen such an operator in Erlang…

That’s because there is no =! in Erlang. What that row is actually stating is that both = and ! are right associative.

Which is actually cool since it let’s you do stuff like…

1> self() ! self() ! self() ! something.
something
2> flush().
Shell got something
Shell got something
Shell got something
ok
3> Pid1 ! Pid2 ! Pid3 ! something. # "broadcast" a message :P

Is that it?

Yeah, I know… this article is not very insightful, deep or revealing as others, but this topic was in sitting in my To-Write list for almost 2 years. Now it’s out of the way.

In Other News…

SpawnFest

As I mentioned in my previous article, SpawnFest is coming!
This year it will happen on September 21st & 22nd.
Register your team and join us for FREE to win several amazing prizes provided by our great sponsors!

ElixirConfLA

ElixirConf is coming to Latin America for the first time!
Thanks to our friends from PlayUS Media, we’ll meet on Medellín, Colombia for ElixirConfLA on October 24th & 25th.
The schedule was already announced, Early Bird Tickets are on sale and the CFT is open until July 19th.

Erlang Battleground

Finally, the usual reminder: We’re looking for writers. If you want to write on Erlang Battleground, just le me (Brujo Benavides) know :)


An Unprecedented Subtraction was originally published in Erlang Battleground on Medium, where people are continuing the conversation by highlighting and responding to this story.

Permalink

Copyright © 2016, Planet Erlang. No rights reserved.
Planet Erlang is maintained by Proctor.