Hi, I am Saša Jurić, a software developer with 10+ years of professional experience in programming of web and desktop applications using Elixir, Erlang, Ruby, JavaScript, C# and C++. I'm also the author of the upcoming Elixir in Action book. In this blog you can read about Erlang and other programming related topics. You can subscribe to the feed, follow me on Twitter or fork me on GitHub.

Why Elixir?

| 19 comments
It's been about a year since I've started using Elixir. Originally, I intended to use the language only for blogging purposes, thinking it could help me better illustrate benefits of Erlang Virtual Machine (EVM). However, I was immediately fascinated with what the language brings to the table, and very quickly introduced it to the Erlang based production system I have been developing at the time. Today, I consider Elixir as a better alternative for the development of EVM powered systems, and in this posts I'll try to highlight some of its benefits, and also dispell some misconceptions about it.

The problems of Erlang the language

EVM has many benefits that makes it easier to build highly-available, scalable, fault-tolerant, distributed systems. There are various testimonials on the Internet, and I've blogged a bit about some advantages of Erlang here and here. In addition, benefits of both Erlang and Elixir are presented in chapter 1 of my upcoming book Elixir in Action.

Long story short, Erlang provides excellent abstractions for managing highly-scalable, fault-tolerant systems, which is particularly useful in concurrent systems, where many independent or loosely-dependent tasks are constantly running.

I've been using Erlang in production for more than three years, to build a long-polling based HTTP push server that in peak time serves over 2000 reqs/sec (non-cached). Never before have I written anything of this scale nor have I ever developed something this stable. The service just runs happily, without me thinking about it. This was actually my first Erlang code, initially burdened with anti-patterns, and bad approaches. And still, EVM proved to be very resilient, and the server ran efficiently from the very beginning. Most importantly, it was fairly straightforward for me to work on such complex problem, in large part owing to Erlang concurrency mechanism.

However, despite some great properties, I never was (and I'm still not) quite comfortable programming in Erlang. The coding experience somehow never felt very fluent, and the resulting code was always burdened with excessive boilerplate and duplication. The problem was not the language syntax. I did a little Prolog back in my student days, and I liked the language a lot. By extension, I also like Erlang syntax, and actually think it is in many ways nicer and more elegant than Elixir. And this is coming from an OO developer who spent most of his coding life in languages such as Ruby, JavaScript, C# and C++.

The problem I have with Erlang is that the language is somehow too simple, making it very hard to eliminate some frequent cases of boilerplate and structural duplication. Consequently, the resulting code gets a bit messy, being harder to write, analyze, and modify. After coding in Erlang for some time, I thought that functional programming is inferior to OO, when it comes to efficient code organization.

What Elixir is (not)

This is where Elixir changed my opinion. After I've spent enough time with the language, I was finally able to see benefits and elegance of functional programming more clearly. Now I can't say anymore that I prefer OO to FP. I find the coding experience in Elixir much more pleasant, and I'm able to concentrate on the problem I'm solving, instead of dealing with the language's shortcomings.

Before discussing some benefits of Elixir, there is an important thing I'd like to stress: Elixir is not Ruby for Erlang. It is also not CoffeeScript, Clojure, C++ or something else for Erlang. Relationship between Elixir and Erlang is unique, with Elixir being often semantically very close to Erlang, but extending the original concept further by borrowing approaches from various other languages. The end result may on surface look like Ruby, but I find it much more closer to Erlang, with both languages completely sharing the type system, and taking the same functional route.

So what is Elixir? To me, it is an Erlang-esque language with improved code organization capabilities. This definition differs from what you'll see on the official page, but I think it captures the essence of Elixir, when compared to Erlang.

Ability to organize the code and to flush out duplication and boilerplate is in my opinion an important role of every programming language. If developers have to constantly duplicate some code structure (such as this one), without being able to eliminate this duplication reasonably easy, then the language doesn't succeed when it comes to code organization. It is in this department where Elixir improves on Erlang, by providing additional tools to organize the code, making developers more efficient in writing production-ready, maintainable code.

Ingredients

Much has been said about Elixir on the Internet, but I especially like two articles from Devin Torres which you can find here and here. Devin is an experienced Erlang developer, who among other things wrote a popular poolboy library, so it's worth reading what he thinks about Elixir.

Here, I'll try to focus on some of the most important tools that help us organize the code efficiently.

Metaprogramming

Metaprogramming in Elixir comes in a couple of flavors, but the essence is the same. It allows us to devise elegant and concise constructs that seems as if they're integral part of the language. These constructs are in compile-time then transformed into a proper code.

On a more specific level, metaprogramming helps us remove structural duplication - a situation where two pieces of code share the same abstract pattern, but differ in various details. For example, a following snippet presents a sketch of a module that models a User record:

defmodule User do
  #initializer
  def new(data) do ... end

  # getters
  def name(user) do ... end
  def age(user) do ... end

  # setters
  def name(value, user) do ... end
  def age(value, user) do ... end
end

Some other type of record will follow this pattern, but with different fields. Instead of constantly repeating this pattern, we can use Elixir defrecord macro:

defrecord User, name: nil, age: 0

Based on the given definition, defrecord generates a dedicated module with utility functions for manipulating our User record. Thus, the common pattern is stated in a single place (the code of defrecord macro), while the particular code is relieved of implementation mechanics, remains concise and easy to understand.

Elixir macros are nothing like C/C++ macros. Instead of working on strings, they are something like compile-time Elixir functions that are called in the middle of parsing, and work on the abstract syntax tree (AST), which is a code represented as Elixir data structure. Macro can work on AST, and spit out some alternative AST that represents the generated code. Since macros are executed in compile-time, the performance of a running system will not be affected.

Owing to macros, most of Elixir, is actually implemented in Elixir, including constructs such as if, unless, or unit testing support. Unicode support works by reading UnicodeData.txt file, and generating the corresponding implementation of Unicode aware string function such as downcase or upcase. All of this makes it easier for developers to contribute to Elixir, since for most feature they don't need to be familiar with another language.

Macros also allow 3rd party library authors to provide internal DSLs that naturally fit in language. Ecto project, that provides embedded integrated queries, something like LINQ for Elixir, is my personal favorite that really showcases the power of macros.

I've seen people sometimes dismissing Elixir, stating they don't need metaprogramming capabilities. While extremely useful, metaprogramming can also become very dangerous tool, and it is advised to carefully consider its usage. That said, there are many features that are powered by metaprogramming, and even if you don't write macros yourself, you can still enjoy many of these features, such as aforementioned records, Unicode support, or integrated query language.

Pipeline operator

This seemingly simple operator is so useful, I actually "invented" its Erlang equivalent even before I was aware it exists in Elixir (or other languages for that matter).

Let me first describe the problem it solves. In Erlang, there is no pipeline operator, and furthermore we can't reassign variables. Therefore, typical Erlang code will often follow this pattern:

State1 = trans_1(State),
State2 = trans_2(State1),
State3 = trans_3(State2),
...

This is a very clumsy code that relies on intermediate variables, and correct passing of the last result to the next call. I actually had a nasty bug in production because in one place, I accidentally used State6 instead of State7.

Of course, we can go around this by inlining function calls:

trans_3(
  trans_2(
    trans_1(State)
  )
)

Notice how the code now must be read "inside-out", the most inner function being called first. This style, known as staircasing, can soon get ugly, and the problem is often aggravated when functions receive additional arguments, and the number of functions in the chain increases.

The pipeline operator makes it possible to combine various operations without using intermediate variables:

state
|> trans_1
|> trans_2
|> trans_3

The code can easily be followed by reading it from top to bottom. We pass the state through various transformations to get the desired result, each transformation returning some modified version of the state. This highlights one of the strengths of FP, where we regard functions as data transformations that are combined in various ways to achieve the desired result.

For example, the following code computes the sum of squares of all positive numbers of a list:

list 
|> Enum.filter(&(&1 > 0))       # take positive numbers
|> Enum.map(&(&1 * &1))         # square each one
|> Enum.reduce(0, &(&1 + &2))   # calculate sum

The pipeline operator works extremely well because the API in Elixir libraries follows the "subject (noun) as the first argument" convention. Unlike Erlang, Elixir takes the stance that all functions should accept the thing they operate on as the first argument. So String module functions accept string, while Enum module functions accept enumerable as the first argument.

Polymorphism via protocols

Protocols are the Elixir way of providing something roughly similar to OO interfaces. Initially, I wasn't much impressed with them, but as the time progressed, I began to understand the benefits they bring.

Protocols allow developers to create a generic logic that can be used with any type of data, assuming that some contract is implemented for the given data. An excellent example is the Enum module, that provides many useful functions for manipulating anything enumerable. For example, this is how we iterate an enumerable:

Enum.each(enumerable, fn -> ... end)

Enum.each works with different types such as lists, or key-value dictionaries, and of course we can add support for our own types by implementing corresponding protocol. This is resemblant of OO interfaces, with an additional twist that it's possible to implement a protocol for a type, even if you don't own the type's source code.

One of the best example of protocol usefulness is the Stream module, which implements a lazy, composable, enumerable abstraction. A stream makes it possible to compose various enumerable transformations, and then generate the result only when needed, by feeding the stream to some function from the Enum module. For example, here's the code that computes the sum of squares of all positive numbers of a list in a single pass:

1
2
3
4
list 
|> Stream.filter(&(&1 > 0))
|> Stream.map(&(&1 * &1))
|> Enum.reduce(0, &(&1 + &2))   # Entire iteration happens here in a single pass

In lines 2 and 3, operations are composed, but not yet executed. The result is a specification descriptor that implements an Enumerable protocol. Once we feed this descriptor to some Enum function (line 3), it starts producing values.

It's worth mentioning that laziness is in no special way supported by Elixir compiler. The general protocol support, and first-class functions are all it takes to implement lazy enumerables.

The mix tool

The final important piece of puzzle is the tool called mix that helps us create and build projects, and manage their dependencies. The tool does its job in a simple and easy way. With a single command line you can create an OTP application skeleton, that consists of only 7 files (this includes .gitignore and README.md). There's not much to talk about mix - it does its job well, and makes it easy to quickly dive into proper development of EVM powered systems.

Other goodies

The list doesn't stop here, and there are many other enhancements Elixir provides, such as support for variable rebinding, optional parentheses, implicit statement endings, nullability, short circuits operators, ...

In general, I like many of the decisions made in this department. It's nice to be able to write if without obligatory else. It's also nice that I don't have to consciously think which character to use for statement ending. Still, I don't find these enhancements to be of crucial importance. They are nice finishing touches, but if this was all Elixir had to offer, I'd probably still use pure Erlang.

Wrapping up

Much has been said in this article, and yet I feel that the magic of Elixir is far from being captured. The language preference is admittedly something subjective, but I feel that Elixir really improves on Erlang foundations. With more than three years of production-level coding in Erlang, and about a year of using Elixir, I simply find coding experience in Elixir to be much more pleasant. The resulting code seems more compact, and I can be more focused on the problem I'm solving, instead of wrestling with excessive noise and boilerplate.

And yet, we get to keep all the benefits of EVM. The underlying concurrency mechanisms makes it significantly easier to tackle complexity of a highly-loaded concurrent system that must constantly provide service and perform many simultaneous tasks.

Personally, I think that both Elixir and EVM raise the abstraction bar, and help me tackle complex problems with greater ease. This is why I would always put my money behind Elixir/EVM combination as the tools of choice for building any server-side system that is at least moderately complex. YMMV of course.

Announcing Elixir in Action

| 3 comments
It's been a while since I last blogged. There are multiple reasons, but the main one is that I'm writing a book called Elixir in Action. The book is already available for sale in the early access version. At this point there are three chapters (you can read the first one for free!), in the rough, unedited version. A 50% discount code eiaaunch50 is currently available, and it will be valid until January 18, 2014.

The aim of the book is to teach how Elixir, Erlang, and OTP can be used to build highly-available, scalable, fault-tolerant, distributed systems. In that sense, it is less about the language, and more about its practical usage, especially in server side systems.

The readers need not be familiar with Elixir or Erlang/OTP, but they should be otherwise experienced programmers, fluent in mainstream languages such as Ruby, Python, C#, Java, ... Knowing about functional programming is not a prerequisite, and the book aims to bring OO programmers up to speed with common functional idioms and techniques.

I came to Erlang after 10+ years of classical imperative OO programming. Being self-taught, and with lack of proper live mentoring from an expert, I made many mistakes trying to make Erlang programming more OO-ish. With this in mind, one of the aims of this book is to guide readers on how to properly use Elixir and Erlang building blocks to produce clean and efficient code.

Beyond the language, various parts of Erlang platform and OTP framework will be covered, such as concurrency, fault-tolerance, distributed systems, releasing and monitoring running systems.

Writing a book is a very time consuming task, and it took me a while to pick up a steady tempo, which is the main reason for the lack of recent posts on this blog. Now that I've got into a sort of writing routine, I plan to blog more regularly, so stay tuned for topics from Elixir and Erlang world!