An Introduction to the Elixir Programming Language (And Why I Love It)

 

I wrote an article a few months ago introducing you to Golang, and why I loved it so much. While I do indeed still love it, lately I’ve been playing around with a new language; Elixir. I bought the book Programming Elixir and have been following it through. I’ve already come to love Elixir and hope to show you why in this article.

Whilst I worked for Couchbase a couple of years back, I took a great interest in Erlang, and distributed systems. To me, Erlang is confusing. When I saw Elixir, I immediately knew I was onto something good. Elixir is detailed as a functional and concurrent language that runs atop of the Erlang VM.

I’ve heard a lot of times, people saying Elixir is ‘Ruby for Erlang’ etc. This theory isn’t fully incorrect, but realistically, it’s mainly just the syntax of Elixir that is influenced by Ruby, as it doesn’t share many of the same programming constructs. It is, of course, similar in ways to Erlang, with it being built atop of the Erlang VM, and giving us direct access to Erlang primitives natively.

Anyway, without further hesitation, let’s dive in and get on with some Elixir.

Installation

If you’re running on OSX, installation is as easy as using Homebrew:
~ brew update
~ brew install erlang
~ brew install elixir

Once you’ve done this, you should be able to run:

~ elixir -v
> Elixir 1.0.2

Now Elixir is installed properly, we can open up an Interactive Elixir and play around with some basic common types.

Types in Elixir

Start up an Interactive Elixir REPL by entering
> iex

Variables:

iex(1)> name = "rbin"
#=> "rbin"

Atoms:

In Elixir, an Atom is a constant in which it’s name is it’s own value.
iex(2)> :this_is_an_atom
#=> :this_is_an_atom
iex(3)> :my_atom == :atom
#=> false

Tuples:

We use the Curly Brace notation to define Tuples. In Elixir, Tuples are stored immediately in memory, meaning getting the size of a Tuple, or accessing a Tuple element is fast, but updating or adding elements is expensive as it requires copying the whole tuple in memory.

iex(4)> tuple = {:hello, "world"}
#=> {:hello, "world"}
iex(5)> elem(tuple, 1)
#=> "world"

Lists:

In Elixir, lists are stored in memory, as linked lists. We can update lists trivially by prepending elements, but appending elements is more expensive, as we need to traverse the whole list to figure it’s size.

iex(8)> list = [1, 2, :atom]
#=> [1, 2, :atom]
iex(9)> ["string"] ++ list
#=> ["string", 1, 2, :atom]
iex(10)> list ++ [31]
#=> [1, 2, :atom, 31]

There are very useful in-built functions to be used with lists, including getting the Head & Tail of a list.

iex(11)> hd(list)
#=> 1
iex(12)> tl(list)
#=> [2, :atom]

Anonymous Functions:

In Elixir, functions are first-class citizens, meaning we can pass functions as arguments to other functions. Below, we’ll define a variable named add which contains a function, that we will then pass as an argument to the is_function/1 func.

iex(14)> add = fn a, b -> a + b end
#Function<12.90072148/2 in :erl_eval.expr/5>

iex(15)> add.(13, 31)
#=> 44

iex(16)> is_function(add)
#=> true

Organising Our Projects (Mix)

Elixir ships with a super useful tool named Mix. Mix is a build tool that allows us to very easily generate, organise, compile, and test our projects. It also makes it easy for us to manage dependencies. (Always a touchy subject!) To create a new project with Mix, we simply do the following:
~ mix new myapp --module MyApp
This will create a directory named myapp with a few files inside. It will also define a module MyApp inside lib/myapp.ex.
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/myapp.ex
* creating test
* creating test/test_helper.exs
* creating test/myapp_test.exs


Your mix project was created successfully.
You can use mix to compile it, test it, and more:

cd myapp
mix test

As we can see, we get all the files needed for a basic project structure. I think this is one of the nicer features available that ship with Elixir. Having project management tools is super useful and a big time-saver.

The file mix.exs is the main file used to configure our project, and manage dependencies etc. We get a test/folder, in which we can write very ruby-like tests for our project. We of course get a lib/folder, which contains the source files to our project. If we run mix test on our app, we get the following:
$ mix test
Compiled lib/myapp.ex
Generated myapp.app
.

Finished in 0.04 seconds (0.04s on load, 0.00s on tests)
1 tests, 0 failures

Randomized with seed 543313

Concurrency

Much like Erlang, Elixir uses the ‘Actor’ model for concurrency. All of our code runs inside Processes, and these processes are isolated from one another. We can make fully concurrent programs in Elixir by spawning Processes and sending and receiving messages between them.

In Elixir, we start processes by using the spawn function, which takes another function as an argument.

iex(1)> spawn(fn -> IO.puts 1 + 1 end)
#=> 2
#PID<0.55.0>

As you can see, we spawned a process which outputted 1 + 1, and also returned it’s Process ID. Returning this Process ID is useful, as we can assign it to a variable, and use it to send messages to the process. Before we do that, we need to create a receive mechanism to attain the messages we send to the process. (We can go ahead and do this in our Interative Elixir session, line by line.)

Once we’ve done that, we can create a process that evaluates area_loop, and assign it to pid.

pid = spawn(fn -> Geometry.area_loop() end)
#=> #PID<0.40.0>

We can then send messages to pid that our predefined code will match on, depending on whether it receives the :rectangle atom, or the :circle atom.

send pid, {:rectangle, 2, 3}
#=> Area = 6
# {:rectangle,2,3}

send pid, {:circle, 2}
#=> Area = 12.56000000000000049738
# {:circle,2}

We can check to see whether processes are still running using the Process.alive? function.

Process.alive?(pid)
#=> false

Conclusion

We haven’t even scratched the surface in this blog. There are so many amazing features in Elixir, I hope you will go on to check it out for yourself. I’ve listed some learning resources below to help you along the way, but before you head off and dive in, here are some of my personal favourite things about Elixir:

  • It was easy to grasp, with a ruby-like syntax, and Erlang-like primitives
  • It’s got a fantastic community behind it
  • It’s concurrency model is both familiar to me, and very powerful
  • Mix is a godsend, and saves ALOT of time
  • Elixir encourages us to document everything
  • It makes building distributed apps a much-less confusing battlefield
  • I can see Elixir going a LONG way.

Resources

Some resources I have found very useful in my short time learning Elixir:

*Go forth and sip on that Elixir! – @rbin *



SendGrid Devangelist. London based polyglot hacker, mainly playing with Golang and Ruby. Musical Hacker, Hardware hacker, Hackathon lover, API abuser and NoSQL user.