Functional programming is fashionable. More and more languages ​​are adopting this paradigm, but more importantly, developers are adopting more and more languages ​​of this type. Scala, F #, Clojure and other old rockers like Erlang or Haskell start to be on the lips of many of the programmers of the sector.

One of the new ones in the city, is Elixir, a functional language, concurrent and thought to make applications maintainable and scalable.

Elixir

Elixir runs on the virtual machine of Erlang (BEAM). This makes the language, despite being very young, is robust and very functional

Elixir is a language created in 2011 by José Valim, and although the syntax is new, the language runs on the virtual machine of Erlang (BEAM). This makes the language, despite being very young, be robust and very functional. In addition, as the language is compiled to Erlang bytecode, functions of that language can be used, without any kind of penalty.

Elixir, like Erlang, is a dynamic language , so failures will be received at runtime. The Elixir typing, although dynamic, is strong, so it is not allowed things that are allowed in languages ​​with a weaker typing, such as JavaScript. For example, the operation 1 + "1"is perfectly valid in JavaScript, but causes a runtime error in Elixir.

Installation and configuration

Installing Elixir is very simple and it is enough to follow the steps that are indicated in its web page. We can install it on Linux, Windows or Mac without too much trouble.

Once we have done so, no further configuration is required. By typing iexin the command line we will access the Elixir REPL (Read-Eval-Print-Loop), which will allow us to execute Elixir instructions. In fact, we could write an entire application from this console.

Elixir logo

Organization and syntax

The syntax is based on the Ruby syntax, so people with some experience in that language will find familiar how to write code in Elixir. Let’s look at an example:


defmodule wesharethis.Syntax.Example1 do

  def print(option) do
    option
    |> get_message
    |> IO.puts
  end

  defp get_message(opt) do
    cond  do
      opt == 1 -> "Hello"
      opt == 2 -> "Hello, World"
      true -> "Hello planet Earth"
    end
  end
end

The functions in Elixir are distinguished by their name and number of parameters (arity)

All the code in Elixir, is organized in modules with defmoduleand within those modules are declared the functions that will compose our application. The functions can be public defand accessible from outside the module, or private defpand accessible only if they are called from within the same module. The functions in Elixir are distinguished by their name and number of parameters (arity) . The function get_messageof the example, is described by the Elixir compiler as get_message/1. If we had another function with the same name, but would receive two parameters would be get_message/2.

Although in Elixir the namespaces do not exist , by convention, the modules are usually named in such a way that they are organized. For example in our example the module is called Wesharethis.Syntax.Example1, which could be something like the name of the project or application, then the group of modules, and finally the specific name of the module. When these names are too long, we can use the operator alias, and thus write only the last part of the name (in this case Example1).

The magic of pattern matching

One of the most interesting features of Elixir is pattern matching. While most functional languages ​​have this type of mechanism, Elixir is used in a very elegant way. The pattern matching is nothing more than looking for a similarity with a pattern, to perform a concrete action. In Elixir, this pattern matching is continuously present, so for example we can see things like these (from iex in this case):


iex(1)> x = 1
1
iex(2)> 1 = x
1
iex(3)> 2 = x
** (MatchError) no match of right hand side value: 1

First we assign the value 1 to a variable. Then we use the operator =to check for matching. In the first case yes there is, since x = 1in the second no, and Elixir shows us an error.

If we complicate the example, we can see that the pattern matching also works with tuples:


iex(4)> {a, b, c} = {1, :error, "not found"}
{1, :error, "not found"}
iex(5)> {2, :error, "null exception"} = {a, b, c}
** (MatchError) no match of right hand side value: {1, :error, "not found"}
    
iex(5)> {1, :error, "not found"} = {a, b, c}     
{1, :error, "not found"}
iex(6)> 1 = a
1    
iex(7)> :error = b
:error
iex(8)> "not found" = c
"not found"
iex(9)> :ok = b
** (MatchError) no match of right hand side value: :error

And that also works with lists:


iex(10)> [a, b, c] = [1, 2, 3]
[1, 2, 3]
iex(11)> a
1
iex(12)> 9 = a
** (MatchError) no match of right hand side value: 1
    
iex(12)> [3, 4, 5] = [a, b, c]
** (MatchError) no match of right hand side value: [1, 2, 3]
    
iex(12)> [1, 2, 3] = [a, b, c]
[1, 2, 3]

As I said the pattern matching is usually a feature of functional languages, but in Elixir is included in such a way that we are almost invited to use it. In fact, when it comes to calling functions it is terribly useful . For example this would be the code of the typical FizzBuzz.


defmodule Wesharethis.Examples.FizzBuzz do

  def start(first, last) do
    first..last
    |> Enum.each(fn(x) -> check(x) end)
  end

  defp check(number) when rem(number, 15) == 0, do: IO.puts("FizzBuzz") 
  defp check(number) when rem(number, 3) == 0, do: IO.puts("Fizz")
  defp check(number) when rem(number, 5) == 0, do: IO.puts("Buzz")
  defp check(number), do: IO.puts("#{number}")

end

If a number is divisible by 3 we write “Fizz” . If it is divisible by 5 we write “Buzz” . If it is divisible by both we write “FizzBuzz” . In any other case we write the number.

In the example we define four functions that are called equal, and that receive the same number of parameters. With the clauses of guard whenwe define the conditions that must be fulfilled so that the pattern matching uses that function. Elixir is checking from top to bottom, which function should be used . Therefore the most specific case must always be at the beginning and the most general, at the end. The good thing about pattern matching in functions is that it does not have to be applied with guard clauses, but we can apply it to the value of the parameter. For example with tuples:


def print_result({:ok, _}), do: IO.puts("operación completada con éxito")
def print_result({:error, message}), do: IO.puts(message)
def print_result(_), do: Io.puts("Error en el parámetro recibido")

In short, pattern matching prevents us from having to write multitude of conditional statements that would make the code more complicated to follow. In fact, the general recommendation is to use pattern matching wherever possible. And in fact it is so simple to do, that we do not usually find impediments.

Functions as First Class Citizens

As a good functional language, Elixir uses the functions as first class citizens. This means that the functions can be passed as parameters, assigned to variables or received as a result of a function.

We have already seen before that we can define functions with defand defp. In addition we can also define anonymous functions:


iex(18)> myfun = fn(x) -> x * 2 end
#Function<6.87737649/1 in :erl_eval.expr/5>    
iex(19)> myfun.(2)  
4
iex(23)> myfun3 = fn(x) -> myfun.(x) + 1 end
#Function<6.87737649/1 in :erl_eval.expr/5>
iex(24)> myfun3.(2)
5

In any case, the functions can be assigned to variables, or even passed as a parameter of another function. For example:


defmodule Wesharethis.Examples.FirstClassFunctions do
  def executor(func, n) do
    func.(n)
  end
end

The function of the example receives another function as the first parameter and executes it passing the second parameter n. In elixir to execute a function contained in a variable, always have to do it adding .(). Two examples:


iex(3)> alias Wesharethis.Examples.FirstClassFunctions
alias Wesharethis.Examples.FirstClassFunctions
Wesharethis.Examples.FirstClassFunctions

iex(4)> FirstClassFunctions.executor(fn(x) -> x * 3 end , 4)
FirstClassFunctions.executor(fn(x) -> x * 3 end , 4)
12

iex(5)> FirstClassFunctions.executor(fn({x, y}) -> x <> y  end , {"hello", " Wesharethis"})
FirstClassFunctions.executor(fn({x, y}) -> x <> y  end , {"Hola", " Wesharethis"})
"Hola Wesharethis" 

Elixir OTP la killer feature

The Elixir syntax is quite affordable for all types of programmers and pattern matching is very accomplished and easy to use, but is this enough to adopt Elixir? Probably not, but if we think about the possibilities we have with OTP, things change.

OTP (Open Telecom Platform) is a set of libraries and functionalities of Erlang, that allow to work of easy form and affordable with concurrent programming. And as it could not be otherwise Elixir drinks from it to offer us the possibility of using it.

actors

Concurrent processes are totally independent and do not share any kind of information

It should be noted that Erlang and OTP were initially intended for use in switchboards, so when designing OTP were based on an actor model. This means that the concurrent processes are totally independent and do not share any kind of information. When a process wants to communicate with another, it can only do so through the passage of messages (through a mailbox), that the destination process will process when it is convenient or possible.

This makes the processes (actors) that we start with OTP are very light and scarcely consume resources, unlike other types of languages, in which the contexts of the processes are heavy and it is more difficult to manage them. The result is that we can boot hundreds of thousands of processes with little penalty for the system. This gives us a truly incredible power.

Obviously, with this level of concurrency, we need tools that allow us to manage the execution (and failure) of the processes that are launched. And for this we have the supervisors.

Using Supervisors

A supervisor is responsible for managing as many child processes as necessary . Supervisors are configured with a specific strategy, which will follow in case any of the child processes have problems. For example, the strategy may be to restart a process when it fails, to restart all child processes when one fails, or not to restart any process when it fails. And all of this is handled by supervisors, efficiently, so we should worry much more about it.

If we launch a process, but this one suffers an exception, its supervisor is in charge of managing it and for example will start a new process of instant form. It is also possible for processes to store a state that can even be preserved in case of failure.

Let it crash

As Elixir processes are so cheap in terms of resource consumption, and being so controlled in the event of failure, an interesting concept emerges: let it crash . Something like that, like letting it fail . And it makes no sense to fill the logic of our processes with exception control. It is simpler and much more efficient, letting the process die and plucking another one in its place. And it is the best practice when using OTP.

Macros

Another important feature of Elixir is the macros. Macros are code that writes code. With them, we can expand the language as much as we want, including elements that do not exist at the base. This is what is known as metaprogramming. In fact, Elixir is full of macros and many of the things that are in its core, are. For example, the clause ifis just a macro. An example that creates a ifcustom would be the following:


defmodule Wesharethis.Macro.If do
  defmacro my_if(expr, do: if_block), do: if(expr, do: if_block, else: nil)
  defmacro my_if(expr, do: if_block, else: else_block) do
    quote do
      case unquote(expr) do
        result when result in [false, nil] -> unquote(else_block)
        _ -> unquote(if_block)
      end
    end
  end
end

The interesting part of the macros is in clause quote do. And that is that the whole Elixir code can be expressed as AST (Abstract Syntax Tree). And is that all Elixir code can be written as a data structure similar to the following:


iex> quote do: 1 + 2
{:+, [context: Elixir, import: Kernel], [1, 2]}

So as we can see with quotewe can access the internal representation of the Elixir code. If we use it in a macro, when compiling, everything that is defined with that macro is replaced by what is represented inside the quote.

Returning to the ifcustom example, we could use it as follows:


iex(2)> import Wesharethis.Macro.If
import Wesharethis.Macro.If
Wesharethis.Macro.If
iex(3)> my_if 1 == 1 do "yes" else "no" end
my_if 1 == 1 do "yes" else "no" end
"yes"

The way Elixir has access to the value of an element and not its representation AST is using unquote. It is important to know that the macros in Elixir are hygienic, that is, that Elixir does the mapping of variables as a last step, so that the variables defined by the programmer in other modules or functions, will not be replaced by a macro. There are ways to skip this rule, but they must be explicitly defined, implying that we know what we are doing.

Elixir has many more things.

While we have commented some of the most interesting features of Elixir, there are many more things to keep in mind. Here are some more:

  • Mix. Tool used for the generation of builds and project management. You can perform a multitude of operations such as compiling, creating a project, running tests, downloading dependencies, etc.
  • ExUnit. Test framework included with Elixir. With some curious options, like the test names, they are a long string saying what the test does, rather than a short name as in other languages.
  • Hex. Erlang / Elixir package manager, which allows us to download dependencies in the purest style npm and similar.

With all these characteristics we can conclude that Elixir is a very powerful language.

Use and Future of Elixir

As more and more Ruby developers move to Elixir, the community is growing rapidly

As more and more Ruby developers move to Elixir, the community is growing rapidly

With Elixir we can write any kind of program. Its concurrency possibilities make it ideal for certain types of backend programs. However, given that web development is the predominant discipline, there is also a framework for developing web applications called Phoenix. Like Elixir is Ruby-inspired, Phoenix is ​​inspired by Rails, though trying to simplify things and eliminate some of Rails’s black magic. The framework is pretty powerful and many Ruby developers are starting to use it, since its performance is really good.

As more and more Ruby developers move to Elixir, the community is growing rapidly. Although it does not reach the breadth of other communities, it is a very active community, which proposes things and helps others to progress. In the Elixir distribution list possible new features or changes to existing ones are discussed; In the Elixir forum there are more general and typical problems that we can find; In the Slack channel we can find programmers debating about the language and the problems that are; And as we can not always get help in StackOverflow, where it is not uncommon for the language creator, José Valim, to answer our questions. Of course,

conclusion

Elixir is a modern and powerful language, but runs on the machine of Erlang, created in the eighties

Elixir is a modern and powerful language, but runs on the machine of Erlang, created in the eighties. This makes it a very robust language and full of features, despite its youth. The syntax, similar to Ruby, makes it more affordable for all types of programmers, away from the academic spirit of other functional languages.

Installing and testing Elixir takes minutes, so do not think about it and give it a try. I’m sure you have a good time.

Author

Am a tech geek.. Do you wanna know more about me..? My contents will do tell you.

Pin It