Pluralsight blog Where devs, IT admins & creative pros go for news, tips, videos and more.
3,500+ tech & creative courses authored by experts - unlimited & online Get it now →
June 19, 2013

Elixir is for programmers

By

The early 2000’s were an exciting time for dynamic programming languages.

Excitement was high for the upcoming Perl 6. It ran on a brand new VM built specifically for dynamic languages and included dozens of experimental syntax sugars such as the hyper operator, which could run a calculation on every element of an array (somewhat like map). I attended the Seattle Perl User Group every month where you couldn’t ignore the anticipation!

It was during these years that I first heard about a weird language that used indentation to define scope (now known as Python). And on January 1, 2001, Dr. Dobb’s journal published an article by Dave Thomas introducing Ruby to the West.

That’s not even counting the other languages I tried out for a few weeks each such as REBOL, RealBasic, and AppleScript.

There must be something special about the start of a decade, because I’m feeling that same kind of excitement and seeing that same kind of experimentation again. At the beginning of May we filmed a 2 hour video with Elixir creator José Valim. Elixir is a language that runs on the Erlang VM but is inspired by the syntax and concepts of many other languages including Ruby, Python, and even Lisp.

It’s not just a transpiler like CoffeeScript; it makes real Erlang .beam bytecode. According to some, parts of Elixir are even more optimized than Erlang itself. It benefits from all the concurrency and deployment options available to Erlang programs. Elixir can call Erlang functions and vice versa.

I don’t pretend to be an Elixir expert (that’s why we worked with José, who is), but I left the session with a lot of enthusiasm for Elixir’s design and features. Here are a few of them.

Smart assert

A programming language like Ruby loses a lot of data when you run it. It quickly loses access to the original source code. If you write a test with Ruby’s basic assert, it can only tell you that the test passed or that it didn’t; it can’t tell you why. Projects like ruby2ruby have tried to bridge this gap but haven’t had support from the core team.

Elixir works directly with your source code to do smart things. Tests rarely need more than the built-in assert, yet meaningful errors can be displayed. Take this Elixir code:

test "makes bacon" do
  assert Bacon.make_bacon() == "avocado"
end

By reading it, we can see that it’s erroneously making bacon but looking for "avocado". We expect that it will fail. If this were a test in Ruby (or any other language), we would see an error such as expected true, got false. Not too helpful.

In Elixir, we see this:

** (ExUnit.ExpectationError)
             expected: "bacon"
  to be equal to (==): "avocado"
at test/bacon_test.exs:14

Elixir knows that == is being used in the assertion, and shows you the values on either side of == when the test fails. Now that’s a useful error!

Multi-block control flow

For years I’ve wanted to be able to write my own control flow structures, such as an each...else that runs an else block if the each is empty (Handlebars templates have this).

The only way to do that in Ruby would be to pass several lambdas to a method, which would be ugly.

In Elixir, the relationship between single line functions and multi-line blocks is well thought out.

These two are equivalent:

# Single line
if(condition, do: a, else: b)

# Multiple lines
if condition do
  a
else
  b
end

In the single line version, if is a function that takes two arguments: the condition and the clauses. The clauses are do and else.

The multi-line version needs no explanation.

But the fact that these two are equivalent means you can write a macro that works just like a built-in. Because that’s how the built-ins are written, too! (source)

Consistent use of do

Developers who love Ruby like the fact that they can override built-in operators and write DSLs that look like built-in Ruby syntax.

But many of Ruby’s syntactical elements are off limits. You can’t write Ruby code that works like a class definition, or an if, or a case...when. Why? class has an end, but no do. There’s no way to write a custom method that takes a block without do.

Elixir is consistent.

Need a module? It’s defmodule...do. Need an if? It also uses do. Same with def.

defmodule MyModule do
  def my_function do
  
  end
end

If you want to write a macro that works like the language does, you can. Because Elixir is implemented with the same tools available for you to use.

Built-in TDD

I find it extremely difficult to learn a new language if I can’t write unit tests. My confidence in writing JavaScript and many other languages went way up once I started using a decent test runner.

With Elixir, it’s built in. Use the mix command to generate a new app and you’re ready to go with a unit test. Run mix test to run the test suite. Done.

It even has conveniences like a test function that takes a quoted descriptive message as the name of the test.

test "extracts m3u8 from index file" do
  m3u8s = Streamers.extract_m3u8 index_file
  assert Enum.first(m3u8s) == Streamers.M3U8
[program_id: 1, bandwidth:
110000, path: m3u8_sample]
  assert length(m3u8s) == 5
end

And it can run your tests concurrently with a single async option (docs).

Mind-blowing metaprogramming: upcase

One of the most ingenious techniques that José mentioned didn’t make it into the final cut of our video.

To capitalize a word, Elixir could implement a single upcase function that keeps a list of Unicode letters in memory and figures out how to translate between them.

Instead, it generates a function definition for each letter. They look roughly like this (source):

def upcase("é" <> rest) do
  ["É"] ++ upcase(rest)
end

A few things are going on here. Elixir can match functions on the number, type, and content of its arguments. So it looks for a letter such as é. It knows the upper case version of the letter, then sends the rest of the string to the next letter’s upcase function.

Pretty cool!

Conclusion

Elixir has many of the features that I look for in a programming language. Its authors have stolen useful features from other languages, it focuses on making it easier to write complex applications, and it has a healthy balance between performance and syntax.

Elixir isn’t the only way to write concurrent applications, but it’s definitely one I’ll be experimenting with for a few months. If you want to learn what it’s about, check out our fast-paced two hour video at PeepCode:

About the Author

is VP of Open Source at Pluralsight. He previously founded PeepCode and is an all around entrepreneur, developer, designer, teacher and athlete. Follow him on Twitter at @topfunky.


Discussion