Learning Elixir: Part 1

Hi All, This should be the first in a series of "Sam learns Elixir" type blog posts I plan on writing as I learn bits of Elixir.

logo

logo

Motivations

I thought it'd be time to branch out from iOS for a bit and learn something completely new. At work, some of our team wrote a job processing system in Elixir and I'd like to be able to understand what the code actually does and be able to help the team where necessary.

What is Elixir?

Elixir is a functional programming language written on the BEAM VM. This is the same VM as Erlang uses. Erlang was written ages ago by Ericsson (the phone company, as in Sony Ericsson) to be highly fault tolerant and massively scaleable. So while the tech isn't new, Elixir is, and brings with it a trendier ruby-like syntax and features like Meta-programming.

First Experiment

So to start with, I watched this talk by Peter Broderick. My goal of this first session was to reproduce the code he wrote in the demo to a working level, and fix that code he couldn't at the end (under pressure, live coding sucks, definitely not judging him!).

SO, brew install elixirand let's go!

The command iexstarts a shell and you can start to play around with it.

Screen Shot 2016-05-09 at 7.53.35 AM

Screen Shot 2016-05-09 at 7.53.35 AM

Some interesting things to note here are that tuples ({1, 2, 3}) are indexable but lists ([1,2,3]) are not. Lists are in fact implemented as Linked Lists, similar to those in Clojure/Lisp so you can get the head of the list and the "rest" of the list as I have done. Of course, Elixir has string and even a concept of symbols - but I'll probably explore both of those at a later time.

Another interesting thing here is the = operator which is actually doing pattern matching, not assignment, which is why I could write [head | tail] = [1,2,3]. Ultimately the same effect if you did something similar in python.

Second Experiment: Mix

Mix is the build tool in Elixir. It is similar to tools you may have used in Ruby/Rails land like bundler, the generators, gems etc where you can generate project and scaffolding files. I used it with the --bare switch to get a reasonably blank project.

Screen Shot 2016-05-09 at 8.08.17 AM

Screen Shot 2016-05-09 at 8.08.17 AM

As you can see, out of the box, you'll get a bunch of sensible files and a test that passes. Then I implemented a few functions to try out the testing suite.

https://gist.github.com/samjarman/a92ecc08e4d22161f15615d9e33d7466

Additionally, similar to Python, Elixir has doc tests which I think are super cool. You can show the doctest how to interact with it as if you were in the shell and then it asserts the output. Neato.

https://gist.github.com/samjarman/ccf4561bedc0b2d8860c3ff50c3d97f5

Experiment 3: Recursion and Private Methods

After this, it was best to get my hands wet with some good ol' fashioned functional programming. So let's create a function which sums some numbers. In imperative programming languages, you could achieve this with a total variable and a loop, but that's a big no no in functional, so we'll use recursion instead.

https://gist.github.com/samjarman/e76d1eb0bfa17834577712109dd994a3

We start off with one public function and two other, private functions (notice the defp). First we can define a function that takes a list and a total variable, where the list is pattern matched into some variables already (see the shell commands above). We'll have for use in this function a tail, a head and total.

For example, calling _sum([1,2,3], 0) would make the variables of head be 1, tail be [2, 3] and total to be 0.

We simply recurse and add it up and continue. The base case is defined above - if we're at an empty list (because the previous calls tail was an empty list) then we can stop and return the total. Sure, a bit complicated, but like all recursive programming it looks pointless on simple examples but looks amazing on harder examples, like tree traversal.

Add a few doctests, run mix test again and we see it works. Boom.

Also it seems that as a naming conventions, private functions are prefixed with _. (Update: Maybe not! Eduardo points out that a lot of Elixir is written in Elixir so that's where the conventions should come from!) Generally I find it a great idea to learn naming conventions alongside everything else with new programming languages. This'll stop the better developers cringing at your code when you inevitably ask for help :P

Experiment 4: Concurrency and Messaging

So I thought it was about time we get to the bit that makes Elixir cool, which is its concurrency model. Long story short, you can spin off threads (except don't call them that, call them Erlang or BEAM processes) trivially and send messages between them. Each process has a "mailbox" and processes communicate by sending messages to each other. Seems simple enough conceptually but obviously we're only scratching the surface of the surface :P

So let's create another process and get it to send us something.

First, we'll get a reference to the current process, by assigning it to a variable called me.

Screen Shot 2016-05-10 at 7.47.09 AM

Screen Shot 2016-05-10 at 7.47.09 AM

Next we'll define a function that uses the send function to send me a tuple with the symbol :hello and the string "hello".

We'll the spawn a process with the spawn command, giving it that function. The process will die once the function has ran. And it's done. It's sent a message. We can check the contents of our main processes' inbox with the flush command.

But now we want to explicitly receive it, so we run it again to get another message in the inbox (previously made empty by flush) and we use a receive block to declare what to do with it. Again here, you see pattern matching taking place that assigns str to the second item of the tuple, if the first item is :hello. We can then print it by using IO.puts strand you see it in the output. Boom. From here you could imagine more complex send functions and receive blocks for many messages, although I'm not yet too sure on how simple they are kept in practice.

That's probably enough for today! There was a bit more in the video, and I did manage to fix Peter's code but I feel this is enough for a single post.

Where to from here? Let me know. Do you know any good learning resources... I'd love to hear about them. Ping me on twitter!