Introduction to Elixir

Erlang

Who This Article Is For

Elixir I would say that the article is mainly for people who already have an experience with some other programming languages, but they want to look around. Also, functional programming is a trending thing nowadays. So if you want to see what it actually is, welcome. If you are a complete beginner, it’s still may be useful, as it’s always good to know what’s going on around the world of IT.

A Few Words about Elixir

A few years ago Jose Valim posted in his repository a project of the language that is built on top of Erlang VM — Elixir. In the article you’ll find extracts from the documentation and a few simple examples. Elixir is the programming language working on top of Erlang Virtual Machine. Just like Erlang, it’s a functional language with strict calculations and dynamic typing. It’s created to support the distributed and fault-tolerant, non-stop applications but also extends it to support meta-programming with macros and polymorphism via protocols. Elixir allows calling Erlang modules without necessity of converting the data types. Therefore, there’s no performance loss when calling Erlang code.

What’s the difference between Erlang and Elixir? Someone may say, that Elixir is a Ruby for Erlang, but that’s not true. Semantically, the language is very close to Erlang, but its code organization is much more improved, as it borrows various approaches from other languages.

A big part of the current standard library is written in Elixir itself. It isn’t necessary to know Erlang to make your contribution to the library development. It will be enough to get familiar with the principles of OTP.

Installing Elixir

Dependencies

In order to begin your work, make sure you have the latest version of Erlang. Elixir requires at least Erlang 17.0 (or later) to be installed. There are several ways you can use to install Erlang. All of them are described here.

If you are on Mac OS X and prefer to install your software via Homebrew or MacPorts:

— Install Erlang with Homebrew brew install wxmac erlang

— Install Erlang with MacPorts sudo port selfupdate

sudo port install erlang

After that run erl to make sure Erlang has been successfully installed.

You’ll also need rebar. I used MacPorts for both Erlang and rebar installations: sudo port install rebar

Elixir

Now let’s install Elixir. Clone the repository and compile it.

$ git clone https://github.com/elixir-lang/elixir.git
$ cd elixir
$ make clean test
$ bin/elixir -v
Elixir 0.14.1-dev

Let’s Get to Work

Similar to erl in Erlang, Elixir has iex — Interactive Elixir shell.

$ bin/iex
Erlang/OTP 17 [erts-6.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (0.14.1-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>

Number symbol “#” denotes comments in Elixir:

iex(1)> # this is a comment
nil

Elixir supports integer and float numbers:

iex(2)> 1 + 1
2
iex(3)> 2 + 15
17
iex(4)> -13 * 10
-130
iex(5)> 1986 - 1985
1
iex(6)> 5 / 2
2.5
iex(7)> 4 / 2
2.0
iex(8)> 0x1F   
31

If you noticed, 4 / 2 returned 2.0, which is float. In Elixir / operator always returns float. If you really need to work with integer, one way is to use div function:

iex(10)> div(4, 2)
2

Variables

Nothing special about variables. Variables should start from a lowercase letter. That’s about it. Technically, they can also start with an underscore sign. In this case it means that you won’t really care about its value later. This is not a language rule, but just a naming convention.

iex(31)> age = 46
46
iex(32)> _age = 87
87

There is one important thing about Elixir variables. It allows you to assign a new value to your variables, whereas most of functional programming languages (including Erlang) doesn’t.

iex(36)> name = "John"
"John"
iex(37)> name = "Larry"
"Larry"

Atoms

Atoms are literals, WYSIWYG components of Elixir. They start with a colon sign:

iex(11)> :atom
:atom
iex(12)> :this_is_an_atom_as_well
:this_is_an_atom_as_well
iex(13)> :yet_another@atom
:yet_another@atom

As you may noticed, atoms can contain underscores and at sign (@). You can also use spaces, but in this case Elixir will want you to wrap your atom with a single quotes:

iex(16)> :'This is my atom'
:"This is my atom"

If you are familiar with Erlang, I shouldn’t explain what atoms are used for. But for those who are not — atoms is a very powerful concept when it’s combined with other data types. I’ll show you some examples a little later in this article.

Lists

Lists are the most useful structures in Elixir (as well as in any other functional language). They can contain anything and considered as an ordered set of elements, which doesn’t have any constraints about its data types:

iex(38)> [1,267,3,9,100]
[1, 267, 3, 9, 100]
iex(39)> [1,267, :atom, 0.9,"Hello World"]
[1, 267, :atom, 0.9, "Hello World"]

You can see that the first list represents a list of numbers and the second one is a mix of different types. Elixir doesn’t really care what you put in there. You can even have a list in a list:

iex(41)> [1,267, :atom, 0.9,"Hello World", ["a list in a list", :amazing]]
[1, 267, :atom, 0.9, "Hello World", ["a list in a list", :amazing]]

Let’s try to do some manipulations with it. Let’s say we want to remove the «Hello World» element from the above list:

iex(43)> List.delete([1,267, :atom, 0.9,"Hello World", ["a list in a list", :amazing]], "Hello World")
[1, 267, :atom, 0.9, ["a list in a list", :amazing]]

Now we have a new list without the «Hello World» element. List is an Elixir built-in module, which implements functions that only make sense for lists. In this case, delete is one of those functions. You can find the full list of modules and their functions in Elixir documentation, which is pretty good and contains a lot of examples.

Strings

Strings in Erlang are represented as a list of characters:

"hello" == [104, 101, 108, 108, 111]

It isn’t quite convenient, since each character occupies 8 bytes of the memory (not bits!). Elixir implements strings in the form of UTF8 binary strings:

iex(46)> str = "Hello World"
"Hello World"
iex(47)> is_binary str
true
iex(48)> String.starts_with? "Hello World", "Hello"
true
iex(49)> String.starts_with? "Hello World", ["Hi", "Hello", "Aloha"]  
true

String is a built-in module, which has bunch of functions that operate on strings as defined in the Unicode standard.

Use operator to concatenate strings:

iex(50)> "hell"  "o world"
"hello world"

Pattern Matching

Just as Erlang, Elixir supports pattern matching. I think showing a quick example is the best way to explain.

Let’s say we have a list of numbers:

iex(71)> my_list = [10,20,30,40]
[10, 20, 30, 40]

Now we want each element of a list to be assigned to a separate variable. If you are thinking about using a loop, then I’m going to disappoint gladden you — we are not going to use anything like that, but instead, we’ll use the power of pattern matching:

iex(72)> [a, b, c, d] = my_list
[10, 20, 30, 40]

Right now we just tried to match left hand side expression with the right-side one, by using match operator =. Let’s see the value of a and c variables:

iex(73)> a
10
iex(74)> c
30

This is just a very basic example. Pattern matching is an amazing tool of many functional programming languages. I could write a separate article just about pattern matching, but for now, I hope you got the main idea about them.

Modules

Let’s build the simplest module.

defmodule Math do
  def fibonacci(0), do: 0
  def fibonacci(1), do: 1
  def fibonacci(n) do
    fibonacci(n - 1) + fibonacci(n - 2)
  end
end

Math.fibonacci(0)   # => 0
Math.fibonacci(1)   # => 1
Math.fibonacci(3)   # => 2
Math.fibonacci(10)  # => 55

Let’s see how the same code looks in Erlang:

-module(math).
-compile(export_all).

fibonacci(0) -> 0;
fibonacci(1) -> 1;
fibonacci(N) -> fibonacci(N - 1) + fibonacci(N - 2).

Whilst Erlang code may look a little bit shorter, Elixir example is much more neat.

I’m still looking into Elixir, but I can definitely say that the language is great. I like that it’s compatible with Erlang, which makes it even more attractive. It reminds me Scala in a world of Java. Hopefully, I’ll write a more advanced article about Elixir and its features. But for now, that’s just about it.

Thank you for reading the article. Stay tuned.

Comments

    3,751

    Ropes — Fast Strings

    Most of us work with strings one way or another. There’s no way to avoid them — when writing code, you’re doomed to concatinate strings every day, split them into parts and access certain characters by index. We are used to the fact that strings are fixed-length arrays of characters, which leads to certain limitations when working with them. For instance, we cannot quickly concatenate two strings. To do this, we will at first need to allocate the required amount of memory, and then copy there the data from the concatenated strings.