Who This Article Is For
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.
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.
— 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
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
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 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 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 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"
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.
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.