5 things to love and hate about the Elixir programming language

In 2015 a new website, Advent of Code, was launched that introduced an advent calendar of programming challenges. The programming challenges at Advent of Code seem pretty well tailored to learning a new language, and because of that I decided to learn a few with the three years of challenges that have been published so far. The first one I picked to learn, Elixir, is billed as a highly concurrent functional programming language with the beautiful syntax and readability of Ruby. I’ve not yet had to use any concurrency operations in the 2015 Advent of Code challenges, but I have spent plenty of time with the syntax and I can tell you it’s a joy to work with. That being said there are some design choices that may make you pull your hair out in frustration if you come from another programming paradigm. Some of these choices are so alien and different that they can inspire hatred in their users. I’d like to show you some of the things I found to love and hate in the Elixir programming language.

Love – Pattern Matching

Pattern matching is one of Elixir’s biggest strengths and it really helps you visualize your data structures when they might get large or confusing to work with. In Elixir, you can specify variables inside of faux data structures to assign variables from functions. Here’s an example when reading a text file into memory.

def read_from_file(path) do
   # File.read(filename) returns a tuple that has a status atom and a string result.
   # Like below, where result is the string containing all the text from the file.
   {:ok, result } = File.read(path)

The example above allows us to extract the result pattern from File.read and return it as the result of the operation. Normally, File.read would return a tuple that we would have to parse after the fact, but pattern matching does the parsing for us and allows us to immediately return only what we care about.

Hate – Loops Require Recursion

It’s really jarring the first time you hear that for loops don’t work in a functional programming paradigm. You see, in functional programming assigning values to variables is evil. So, whenever you want to run a for loop you assign an indexing variable (usually, it’s labeled ‘i’) and increment it every time you finish an iteration. This method produces side effects and is not compatible with a functional programming model where every assignment must not change once it’s happened. Here’s an Elixir example of printing hello world n times where n is the increment variable.

def for_loop(increment) do
   IO.puts "Hello world!"

def for_loop(increment) when increment <=1 do
   IO.puts "Hello world!"

As you can see, this requires a whole lot more code than a simple for loop in an imperative programming language. Technically, it is immutable and won’t produce side effects, but it makes the code much harder to read and write.

Love – Immutability

Immutability, which is what makes loops hard to write in Elixir, is also one of its biggest strengths. Functional programming generally requires immutable data structures, and this means it can be more expensive (time and memory wise) to write functional programs (heh) instead of imperative ones. You’d think that it would be a no brainer to use an imperative language all the time, but imperative languages produce code that is hard to verify than functional languages. In functional languages, given one input, you always receive one output regardless of the state of the system at that point in time. While working with file systems and other system utilities can’t guarantee foolproof execution you can expect anything internal to your program to produce one output.

Hate – Erlang functions

At first glance, there’s not a good stdlib for Elixir, but this is because Elixir uses a lot of Erlang’s stdlib. That’s great, but I signed up to learn Elixir and not Erlang. Elixir is built on top of Erlang, though, and you can type Erlang code in your Elixir program and compile it with no problems. This doesn’t really sound like something I should be upset about, and I normally wouldn’t be offended by good interoperability, but in this case Elixir is not necessarily up front about Erlang or what you would need it for. Yes, the Erlang VM is emphasized on the Elixir language web site, but the ability to use Erlang code in Elixir code is not front and center. It’s a small gripe, but it was the only other thing I could think of to complain about.

Love – Tooling/Testing

The mix command line tool is probably one of the best CLI tools I have used in my life. Based heavily on tools like Ruby’s rake and C’s make, mix is a tool that allows you to manage dependencies and compile and test your application. The test runner, ExUnit, is really easy to get started with and allows you to write doctests that document and test your code at the same time. You’ll find an example below:

@doc """
  Adds two numbers together.
  ## Examples

      iex> Math.add(2, 2)

  def add(a, b) do
    a + b

The examples portion of the documentation will be run as assertions using ExUnit, so if you were to change the four underneath the example to 5 it would fail assertion. This type of testing makes your code self-documenting and easy to read and use. Mix enables this by default and is really the way that all mix packages should be written.

There’s so much more to Elixir than what I’ve already elaborated on. While there’s probably a great deal of headache I haven’t run into yet, there’s a lot more to love about Elixir than to hate about it. I didn’t even touch on the IEX interpreter, the pipe operator for chaining functions, the Hex package manager, or the excellent Phoenix Framework built on top of Elixir. If you’d like to learn more visit the links ahead for Elixir, [](https://elixir-lang.org/)[Mix](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html), ExUnit, Hex, or the Phoenix Framework.