Just for fun, I thought it would be exciting to learn something new. Not just a new language, but a new paradigm of programmning. I’ve read a bit about Functional Programming over the years, and even dabbled in college with Lisp and Prolog, but I never took the deep dive… until now.
The urban legend is tall and long - Dude, one programmer on a raspberry pi hosted a billion users and the code ran for like a million years! Well, I think the hype might be exaggerated, but the truth is pretty awesome. There’s so much going on in Erlang/Elixir that at first glance it can be overwhelming for someone coming to it with zero experience. And, making matters worse, coming to it with ZERO experience with functional programming is an even larger leap.
Where to Begin
So, I started the journey with basically zero experience with functional programming and no experience with Erlang/Elixir. And with a lot of reading, writing, and question asking - in roughly 12 weeks - I’ve become very comfortable with Elixir, OTP, Metaprogramming, and even some Erlang. I thought I’d write about how to navigate the seemingly daunting process of becoming proficient.
You need to first get a development environment setup. This encompasses the Erlang/Elixir environment and an editor of choice. There are essentially two choices: building from source or a employing a package manager:
Regarding an editor, the best option here is to use your editor of choice, and then add the subsequent extensions to give you the fancy syntax highlighting and autocompletion to make your entry into Elixir that much easier. I use both Atom and Vi equipt with the above extension. For those using Sublime, you’re in luck with the aftermarket add-ons also available to ease your editing.
Okay, you successfully installed Erlang/Elixir, set up your editor - now what?? Well, we have a few thing we need to do first. We need to step back and take a tour of the Elixir language and learn about the syntax, structures, and programming paradigms that broadly encompass the language. To do this, we need to understand how to interact with the Elixir environment and to experiment and understand what these things are and how they behave.
I’d start with the official website - specifically, the Getting Started section. Work through all 1-22 sections.
The first section is going to introduce you to the Elixir Interactive REPL - iex. This is an indispensible tool to play and experiment, and learn!! Along with iex there is elixir and elixirc a script interpreter and compiler respectivly. Finally, there are escripts which are binary files that execute from the command line. More on that later.
One cool thing about the REPL is that there is a TON of documentation built into the tool. Virtually all of the code is documented in iex. Start off by asking for help by running the help function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
There’s a lot to learn in these first Twenty-Two sections:
Pay close attention to these major concepts: - Pattern Matching - Processes - Recursion - Enumerables and Streams - Lists, Maps, and Tuples.
Focusing first on getting these basic Elixir concepts down will make learning the other more interesting topics far easier. Once you feel that you’ve mastered these Introductory elements, take a look at the meat of Elixir:
Now that you’ve taken a broad cursery overview of the language by reviewing the website, familiarizing yourself with the tools, and experimenting with the language using the iex REPL, it’s time to dive into a few books to add to our newly developed perspectives.
I found the following books very helpful:
And in addition to the website and the books, I strongly recommend joining the elixir slack channel. There are so many knowledgable and generous people on the Slack channel willing to help you understand concepts that may seem foreign or opaque to the noob. Ask away!
So you’ve learned the language, experimented with some of the features, maybe even learned how to use the GenServer, Supervisors, and did a little meta-programming. What’s next??
Elixir is well suited for distributed computing. iex starts a Virtual Machine called the BEAM. Elixir makes it easy to connect multiple BEAMS together to solve a problem.
Here’s a quick example of how easy it is to start two BEAMS and get them talking!!
First we need to name each BEAM and give it a shared secret that will be common among all of the participating nodes.
Then we’ll need to connect the nodes and share our code.
Lastly, we’ll need to run the code on all of the BEAMS. Wow, that sounds complicated. And indeed in many languages, contemplating such a task would be fraught with coding challenges and gotchas. Not so much in elixir.
Take a look:
First, let’s start two separate iex BEAM VM’s:
and in another terminal window…
Now we gave each instance its own name, and we set a cookie that allows each to connect to the other.
Next, we need to connect them. That is to say, make each node aware of the other. The simplest way to connect a node is to ping it!
On foo - let’s ping bar.
If you didn’t get a :pong back, you’ve goofed. Confirm that you’ve connected the nodes together by listing the Nodes.
Now we can define a module on foo and send it to bar. In order for us to send the code to other nodes, we need to have our module compiled into a beam file. So, in your editor on a third terminal, define a basic module and save it to a file in the same directory that you ran the iex REPLs in:
1 2 3 4 5
How do we compile this module definition into a beam file? We can use iex (
c/2 - see h c/2 for more info), or we can compile it using elixirc.
This will generate a file named
Elixir.Boo.beam. Now we can move this code throughout our connected Nodes using the
nl/1 function in iex.
This returns a tuple with :ok and a list of three-tuples. The code has now been successfully distributed to the other connected nodes - an we can run it! There are two ways to run the defined function in
Boo. We can type into the iex on bar and run it
Boo.hi. Or, we can run it from
1 2 3 4
and to retrieve the value sent from bar to foo we can use flush() thereby retrieving the message sent from bar to foo’s process:
It’s that easy! Of course this was a trivial example. But the point is to demonstrate how easily and quickly one can develop a distributed application. Instead of sending a message, we could have just as easily performed a complex computation - using the power of all of the CPUs in the Node list.