Elixir for Java Developers, Episode I

Jusabe Guedes
SkyHub Labs
Published in
6 min readMay 23, 2017

Recently I decided to change my way of thinking by learning a new programming language. I’ve been working with Java since the beginning of my career, so a totally different paradigm was necessary. Then I found this amazing language called Elixir.

If you are from the Ruby world you've probably heard about Elixir. Perhaps even know its creator, José Valim. But if you come from a more verbose side the chances of being familiar with Elixir are pretty low.

So I decided to make some posts to help people from Java background learn faster how Elixir is designed. Making some comparisons between them will be way easier to understand this new Elixir world. Through posts I'll talk about syntax, how things work and key features that make Elixir awesome!

Functional Programming

Put all the objects, classes and interfaces aside for a moment. Elixir is a compiled functional programming language that has immutability as its foundation. You just need to keep in mind three simple rules to quickly get how things work.

  1. Everything is immutable.
  2. Functions are idempotent. It means that no matter how many times a function is called with the same arguments, it will always produce the same result.
  3. Pattern matching rocks!

Say Hello!

Everybody that is learning a new language needs to know how to do the fascinating "Hello world!". Here would not be any different.

//Java
public class HelloWorld {
public static void main(String[] args){
System.out.println("Hello world!");
}
}

#Elixir
IO.puts "Hello world!"

Types and Variables

Variable types in Elixir are dynamically inferred at runtime. So when we declare a new variable we don’t need to explicitly say its type. Here are a couple of basic types with its differences on how to instantiate them.

//Java 
int i = 1;
float f = 3.0f;
boolean b = true;
int[] array = {};
String s = "foo";
Map<String, Integer> map = new HashMap<>();
#Elixir
i = 1
f = 3.0
b = true
list = [1, 2]
s = "foo"
map = %{"one" => 1, "two" => 2}
tuple = {1, 2}
keyword_list = [one: 1, two: 2]

Now imagine that we have a list and we need to add a new element to this list. The following Java code show us how to doing it.

//Java
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.size(); //returns 2

It's time to remind you of our first Elixir rule: everything is immutable! If we want to change the value of any variable, we need to explicitly rebind it to a different value. At the code bellow only the first three lines are changing the value of ‘list’. The others lines aren't changing the 'list' value, it's just creating a copy with the new values.

#Elixir
list = [] #creates a list
list = [1 | list] #prepend 1 to the list
list = [2 | list] #prepend 2 to the list
Enum.into(list, [3]) #prepend 3 to the list
list ++ [3, 4] #concat the two lists generating [2, 1, 3, 4]
Enum.count(list) #returns 2

Here goes a bonus tip about Lists in Elixir. They are stored as linked lists. Since we only have a reference to the head of the list, if we want to simply add a new element to a list, we need to prepend it replacing the head. It will guarantee an O(1) insert. There is no append, but if we still need to put something at the end, our option is concat the current list with the new element wrapped in a list as shown above. Be careful with that because it's an expensive operation since we need to copy the entire list and create a new one.

Another gotcha is when we need to know the list size. As you may have imagined, the only way of knowing is to transverse the whole list and count how many elements are in it (O(n) complexity). Again, use it with caution.

Don't worry, that is just because we are used to think in an imperative way. Besides that there are others alternatives that I will talk about later. For now let's do what the company with the fruit logo says:

Think different!

Functions vs Methods

Differently of Java methods that can receive four types of access modifiers(public, default, protected or private), Elixir functions has only two types(public or private). Public and private functions starts with 'def' and 'defp' respectively. Both types can be declared in different ways as shown bellow.

//Java
public void addElement(List<Integer> list, Integer element){
list.add(element);
}
private int privateSum(int a, int b){
return a + b;
}
#Elixir
def say_hello(person) do
"Hello #{person}"
end
def prepend_element(list, element) do
[element | list]
end
def sum(a, b), do: a + bdef sum a, b, c do
a + b + c
end
defp sum(a, b, c, d) do
a + b + c + d
end

As you have noticed we have different ways of declaring a function and didn't put a return in our Elixir functions. It's because the result of the last instruction inside a function will always be returned to the caller.

Now let's got back to the adding a new element into a list again and use the functions we've declared above. Because every object in Java is a pointer, when we pass an object to a method as argument, a copy of that pointer is created to be used inside the method. It means that unless we reassign the ‘list’ inside ‘addElement’, any change we make on the list will reflect outside the method. Elixir works way different than that.

As mentioned before on our second magic rule, Elixir functions are idempotent! Besides the returning value, everything we do inside functions stays there. This is one of the key features that enable things to run isolated and achieve an whole new level of parallelism. No need to worry about side effects here.

#Elixir
list = [1, 2]
prepend_element(list, 3)
prepend_element(list, 4)
prepend_element(list, 5)
IO.inspect(list) #returns [1, 2]

I couldn't end this section without talking about the Elixir pipe operator "|>". Using the pipe we can easily chain functions passing the result of the previous function as first argument to the next function on chain. Here is a silly example how we could use it.

//Java
String fullName = "my full name";
String[] names = fullName.split(" ");
String firstName = names[0];
firstName.toUpperCase();
#Elixir
"my full name"
|> String.split
|> List.first
|> String.upcase

Modules vs Classes

In order to do anything in Java we first need to create a class. It will contain constructors, methods and variables. In Elixir we have modules, responsible to hold together our functions. Here are how they looks like.

//Java
class Calculator {
public int sum(int a, int b){
return a + b;
}
}
#Elixir
defmodule Calculator do
def sum(a, b), do: a + b
end

See modules functions like static methods inside a class. We don't have the notion of instances, so every module and function are "static". We can see the usage difference bellow:

//Java
Calculator calculator = new Calculator();
calculator.sum(1, 2);
#Elixir
Calculator.sum(1, 2)
#the parenthesis are not mandatory
Calculator.sum 1, 2

Coming soon..

Well, this is only the start of many posts that will come. On the next ones I will be approaching things like control flow, pattern matching, recursion, etc. Stay tuned!

I hope you guys have liked it. If you have any comment or feedback let me know. =)

Next Episodes

--

--

Jusabe Guedes
SkyHub Labs

A software engineer who doesn’t drink coffee and wants to be a digital nomad.