A Front-End's (good) impressions about Elixir

Eve Montalvão
Inside SumUp
Published in
6 min readAug 18, 2020

I’ve been working almost exclusively with Javascript/Node.js since 2016, but since February I’m in a love-hate relationship with Elixir, sometimes more hate than love (way more hate), but I had to admit that Elixir has its charm. I ended up working with Elixir because since my first contact with Node.js I wanted to have a more challenging experience with back-end. Don’t get me wrong, Node.js is challenging, but I was already familiar with Javascript and that made it easier for me. After a few interviews at SumUp, the interviewers noticed my interest in Back-End and gave me the opportunity to work with Elixir, even though I had no experience with it. And I am so grateful for that.

So, getting back to coding, my first impression was that Elixir complicates everything, but it actually gives us some different ways to think outside the box. I’m going to talk about some features that really got me, starting with Pipe.

Pipe

The pipe operator |> passes the result of an expression as the first parameter of another expression.

Before I knew pipe, I already loved its purpose. In JS, we have two ways to implement the pipe’s concept: creating a compose/pipe function or using method chaining.

Method Chaining:

When we talk about method chaining is very common to use Array Methods as an example. You can chain every Array method like the following because they all return the magic word: this. But unfortunately, we can only use this when it comes to objects or classes.

Compose/Pipe:

In the example above we are chaining three functions. First, we get the first name, then we make it lowercase and, finally, we get only the first letter of the name. Each function passes the result to the next function. Compose is almost the same thing, but backwards.

In Elixir we have this very elegant way to do that:

The biggest advantage I see is to be able to pass multiple and different parameters to each function, like this:

The string “Montalvão” is passed as a second parameter to get_fisrt_name function only. There is a way to pass the same multiple parameters to all functions, but it’s not what we want, we want to be able to pass different parameters to different functions. The easiest way I managed to do this in JS is like this:

Each function expects two parameters and since we are encapsulating each of them in an anonymous arrow function, we can pass different parameters, but this is not very classy, right? The proposal of pipe operator in Javascript is currently in stage 1, so there’s a chance that we can have it in JS in the future. I’ll drop the reference links at the end of this article.

Pattern Matching

Pattern matching is a powerful feature that allows us to look for patterns in any value or data structure.

It can be a little confusing, but I promise it’s cool, in fact, it’s my favorite Elixir feature so far. In Elixir the = is called Match Operator. So, when you use it, you are comparing the values on the right with the values on the left. See the following example:

Ok, I know there’s nothing special about it and we can do the same thing with JS’s “destructuring”, but I swear it’ll get better.

If we try to do the following, we’ll get an error:

Want to see something weird? If we do the following, we also get an error:

[a] = [1, 2]

What? How? Why did this happen when we definitely have a value to bind the a variable? This means that Elixir can’t match the two sides because they’re not equal in size. In the first example, we don’t have any value to bind letter d, so they’re not equal and we get an error. In the second example, we get an error because a list with 1 element could never match a list with 2 elements. This can be confusing for JS developers because when we say [a] = [1, 2], we are assigning the first value of the array to the variable a.

You’re probably thinking right now: “Ok, Eve, but why is this cool? I honestly think it’s terrible to receive an error for something so simple. Javascript would have undefined as the value of d and that’s good for me”. Well, that’s right, but when you understand the power of pattern matching it makes sense. Pattern matching is very useful when you need to deal with different cases in the same function. Let’s take a look at a real use case: At SumUp we have this module called FallbackController, we use it when we need to send some response to the client, through the method call:

At the code above we have this function called call that is pattern matching its parameters. The only way to get into this function is to send the second parameter like this:

{:ok, %{ prop: “value”, anotherprop: “value” }}

If we try to send the following as a second parameter, our call method will never be called.

%{:error, %{prop: “value” }}

This happens because pattern matching can be used in function parameters as well. The value doesn’t match? The function is not called. So, let’s improve our FallbackController. We already have a method to deal with successful responses, let’s make one to deal with an error.

Now when we call our method with {:ok, %{ prop: "value", anotherprop: "value" }} , the first one is called. When we call with {: error, %{ message: "Something went wrong" }} , the second one is called. And we can keep going until we cover all the cases we need.

I see this as a very good way to apply the single responsibility principle, since we can handle each case in its own method, instead of a messy single method with a bunch of if/elses (which is strongly not recommended in Elixir).

Another very interesting way to use pattern matching is within case, like this:

The case statement works almost like our JS’s switch/case statement, but it allows us to use pattern matching instead of matching the exact value. Of course, we can also do exact matches, but I like how flexible case is. Let’s take a look at these other examples where I used ^ to let Elixir know that I want the first item of the list to be equal to our x variable. If the value is anything different than x’s value, the pattern will not match.

You can even check if a value is greater/less than another value, or maybe do more complex operations by using when.

Another great feature is that we can mix pipe and case. Remember our pipe example? Let’s use it again, but now within case statement.

I know this is a very dumb example, but I believe that dumb examples are best when trying to understand a language you don’t know. Well, since we’re talking about case statements, this leads me to the last feature I’m in love with (in case you didn’t notice, I tried to make a joke here because the name of the statement is with).

With

The special form with/1 is useful when you might use a nested case/2 statement or situations that cannot cleanly be piped together.

The with statement gets the case statements and takes it to another level. Imagine a usual API call where the only response that matters to us is the successful one.

In JS, again, the closest thing we can do is “destructuring” the response object and check the value, but it’s more verbose and it would be something like this:

Another use case is when you need to check for multiple case statements within different sources of data, with can do this like a charm.

The with execution stops at the first non-matching line and the else block is executed, and guess what? We can also match our else, if necessary. Pretty cool, right?

If you’re a Javascript/Node.js developer looking for a new language to learn, especially if you want to learn more about functional programming, I think you should give it a try. Of course, Elixir has its bad side, for example, I’m used to having plenty of articles, a big community, clear documentation and Elixir isn’t always like that. Sometimes I struggle to understand some things because of the lack of content on the internet compared to Javascript, but it’s kind of our job to change this by creating more content.

And if you’re interested in learning more about pattern matching and pipe proposals for Javascript, check these references below:

Explanation of a Pattern Matching proposal in JS

Pipeline Operator Proposal

SumUp is hiring, click here if you want to be a part of our team!

And last, but not least: share with your back-end enthusiastic friends if you enjoyed this article.

--

--