From Ruby with Love

How an OO developer visualizes processes in Elixir

Meryl Dakin
Flatiron Labs
5 min readJun 12, 2019

--

James Bond using the powers of the Erlang Telecommunications system

From OO to Elixir

When you’re coming from OO to Elixir, you hear about “parallelism” and “fault tolerance” and how great they are. You learn that these things are made possible through functional programming and OTP. And so when you start coding in it, you parrot these things back to people who ask you why Elixir is so cool. But after months of deftly dodging the question “Wait, what is the BEAM?”, you need a new tactic.

What helped me was understanding the common goals of OO and functional programming and recognizing their shared ancestry, because understanding a premise can often help us arrive at the correct conclusions.

The Elixir Family Tree

If Elixir signed up for 23andMe.com, it could trace its origins all the way back to old Grandmother Message Passing.

Message passing was born in the 1970’s, an idea Carl Hewitt and Alan Kay came to when describing how entities in a system can work together. It’s simple: two entities communicate with each other by sending and receiving messages, just as two humans would. Take these humans for example:

One human passing instructions to another one.

The human on the left is giving the one on the right instructions. Can she be sure he will carry them out? No, but she can’t concern herself with that. The human on the right has received her message and will do with it what he will. This is the way Hewitt and Kay envisioned parts of a system interacting. It developed into the “Actor Model,” in which every entity is an isolated actor that can send messages to each other.

However, there was a split in the way they carried this out. Kay went on to create Smalltalk, an early OO language, where the objects communicated by sending messages to each other. Hewitt went in a functional direction, developing PLANNER which lead to Prolog.

But the cross-pollination of their ideas both contributed to the birth of Erlang. Joe Armstrong, one of its creators, wanted to retain the message-passing from OO but he saw problems with its strong coupling of data to functions. He took a lot of the syntax and procedural approach from Prolog, and initially implemented Erlang in Prolog.

Just as in the Actor Model everything is an actor, and in OO everything is an object, the building blocks of Erlang and Elixir are processes.

Processes

  • Are isolated; have private internal state
  • Communicate by sending/receiving messages
  • Act independently of each other
  • Are part of but do not know the big plan

Here’s an example of a suuuuper simple process, one that only counts up.

We spawn this processes with the execute function and an initial value of 0 (spawn(CountUp, :execute, [0])). That allows us to hook into these receive and send blocks that handle message passing. If we start the execute function with this process and then send it the message add, it will output Adding! to the terminal, then call the execute function again with 1 added to our initial number. This allows us to “change” that internal state while keeping it private; nothing else can reach into this function and alter it.

With all that in mind, I’ve found a way to help me visualize this in a real-world scenario: spies.

Processes are like spies

Specifically, they’re like sleeper agents.

Sleeper agents ‘wake up’ and perform a specific set of tasks while living under cover in an area of interest.

This makes sense. Sleeper agents aren’t going to like, spy meetings and stuff to share their intelligence. They’re just working on their own tasks, independently of each other, and communicate through secret message instructions to each other. What might that look like?

Spy in secret bunker

Let’s notice what this spy has at his disposal:

  • An inbox for incoming messages
  • A legend on the wall to decipher the messages and match them to a task
  • A table of tasks, secret formulas he can make
  • Very cool sunglasses

Now let’s say our spy gets a message.

Spy deciphering message

Our spy is going to first match that incoming message against the legend on his wall. Let’s remember that’s the same as our process receiving add and needing to match it to one of the cases in the receive block. If it got something like bark and it didn’t have that case, it wouldn’t do anything with the message. Just like our spy: if he got a message that didn’t match one on his wall, he would throw it away, might be from an enemy!

But thank God he matches this one. It’s a blue star, which points to formula C.

Spy performing task

Now our spy can make his formula. Notice that while he’s making the formula, he might get another message in the window — no matter. He has to first complete this task before moving on to the next instructions.

What’s really exciting about this situation is that our spy is working completely isolated from his environment. So while this spy is performing his tasks, we can have a whole crew of spies working on their own formulas:

Spies doing spy things

None of the activities of these spies are impeding their comrades. And because of this, we’re allowed to have them work at the same time.

Next up: mission failure

Where are all these messages coming from? What happens when a spy fails to perform his mission? Part two coming soon.

Thanks for reading! Want to work on a mission-driven team that loves intrigue, espionage, and OTP? We’re hiring!

Footer top

To learn more about Flatiron School, visit the website, follow us on Facebook and Twitter, and visit us at upcoming events near you.

Flatiron School is a proud member of the WeWork family. Check out our sister technology blogs WeWork Technology and Making Meetup.

Footer bottom

--

--

Meryl Dakin
Flatiron Labs

Dev at Knock.app. @meryldakin on github, LinkedIn, and twitter.