Let's dive into functional programming and discover the benefits of this new paradigm with the Elixir language.
Perhaps you are wondering what a functional programming language is? Or maybe you want to learn more? In this article we will talk about functional programming and more specifically about functional programming with Elixir. Elixir is a language with a syntax that is quite simple to understand. It will allow you to familiarize yourself more easily with functional programming. We will also see what the advantages of this programming paradigm are.
Functional programming is a way to approach computer programming. It is called a paradigm. The five most represented and used paradigms are the following:
Each paradigm has its own way of working, so here we will focus on functional programming. The biggest advantage of this one is that it will allow to take advantage of the current processors. Indeed, the functional programming will be able to best use the competition of the processes and the parallelism that they offer. This is to obtain faster programs, the response time of these being an extremely important element nowadays.
Some paradigms such as imperative programming do not allow as much use of the processor as a functional language such as Elixir would. Indeed, the main disadvantage of imperative languages is that they have shared values that can be modified. Let's imagine for example a simple list like this one:
list = [“A”, “B”, “C”]
To modify it we have functions at our disposal, for example :
Using a function of this type in an imperative language our list "list" would take the value [“A”, “B”]
In Elixir, which is a functional programming language, the list "list" would always have the same value, i.e. [“A”, “B”, “C”]. Nevertheless the result of the function List.delete(list, “C”) will return [“A”, “B”]
So that's the big difference between these two paradigms. Now imagine several functions that manipulate the value of our list "list" and all at the same time. The risk of error or unexpected behavior is huge in an imperative language because the value of the list can change at any time. This is why it is much more complicated to take advantage of current processors with this type of language.
On the contrary in functional the value of the list will never change, it is immutable. This makes it possible to use it concurrently and in parallel. Several functions or processes can manipulate the list without risk because its value will not change unexpectedly. Functional languages also aim to make the best use of functions to create clean and maintainable software. Moreover, they are declarative, i.e., calling one of their components with the same arguments produces exactly the same result, whatever the time and context of the call.
Elixir is a functional programming language although it is also considered a multi-paradigm language. It runs on the Erlang Virtual Machine (BEAM) which allows applications written in Elixir to function. Its creator, José Valim, wanted to create a programming language for large-scale sites and applications. It was created to take full advantage of the multi-core processors that began to be fully democratized in the 2000s. It is particularly used to create low-latency and fault-tolerant distributed systems.
In functional programming, functions have a very important place. Indeed, each function will receive data as input, these data will be processed by the function (calculation, formatting, ...) then the result of these operations will be returned as output. These are the functions that will form your program. Since functions can multiply and become complex very quickly, it is recommended to create functions with a single task. Moreover, each task must be as simple as possible. Finally, each function must be explicit, we must easily understand what its role is.
The best way to create the "cleanest" programs possible is to use "pure" functions. For a function to be considered pure, it must respect three rules which are the following:
If these three rules are respected then the function is said to be pure. It is the case, for example, of a function which carries out simple calculations like this one:
Here the result of the function is predictable. Moreover the function does not generate any effect apart from the value it returns and finally the result is only affected by the arguments given as input.
Conversely, impure functions return results that can be unpredictable. We will see this later.
Moreover, in functional programming and in Elixir, functions are so important that it is possible to use a function as an argument to another function!
Let's take this example:
In this example we can see that we have a function Enum.map, this function takes here 2 parameters. The first one is a list of integers and the second one is a function (Integer.to_string). As you may have already understood, we want to transform each of the integers in the list into a string. The Enum.map function then understands that we want to apply the Integer.to_string function to each of the elements in the list. The result is a list of integers converted to string format.
Now you may think that the code will quickly become unreadable if we start using functions within functions. This is without counting on the intervention of the "pipe" operator. In Elixir there is indeed an operator that will allow us to simplify the use of several functions one after the other. This will make the code more readable and above all more understandable.
In many languages you can use results of functions in other functions like this:
OR if you want to make your code a little less complex:
In Elixir there is a much better way to do this thanks to the pipe! The pipe operator is presented in this form "|>". It can be used in the following way:
As you can see, the code is greatly simplified and it is easy to understand what is being executed. The result of function_3 is passed as a parameter to function_2 and the result of this function is passed to function_1. The final result is exactly the same as with the two previous examples, but with a much more readable code.
Finally, there is a major difference between functional languages and imperative languages. Indeed, Elixir and all other functional languages are declarative languages. This means that they focus on what to do to solve a problem while imperative languages focus on how to solve it.
Often by concentrating on what to do we need less code to achieve the same result than by thinking about how to do it. This is a big advantage since less code also means less time, fewer difficulties...
If you have never done functional programming, the transition may be complicated for you and that is normal! To move from one paradigm to another you have to rethink your whole way of thinking. By switching from one object-oriented language to another, we have no trouble adapting. The great difficulty is to move from one paradigm to another. But once you have understood the different mechanisms, you will be able to take full advantage of functional languages and all that they bring! Of course, using a functional programming language is not always the best solution for your needs. The best is to master several paradigms. Nevertheless, functional programming brings a lot of useful features.
At Cryptr we use functional programming and more specifically Elixir to develop our applications. If you want to learn more, feel free to contact us, check out our other articles or visit our social networks like LinkedIn, or Twitter!