Elixir notes II – Anonymous Functions

Elixir is a functional language, and as the name says “functional”, one of the core parts of the language is its functions. All projects written in elixir are composed of tons of functions chained, and know how to deal with functions is a core part of every elixir programmer. On these notes let’s travel on a journey across all the ways to handle functions in elixir code.

In the first steps after writing our first “hello world” we usually learn about functions and its important mission of making a big sausage code divided into small pieces of meaningful code, that can be reused later, making our software more readable and less complex.

I think every programmer knows what its functions and how to use it in our code, but functions in the elixir can be a little bit different from those coming from some languages, especially object-oriented language that deals with mutating objects.

Most functions in elixir are what we call “pure functions”, it means that our functions will always have the same output for a given input and that it won’t generate effects that are not the value that it returns it is possible because in elixir everything is immutable by default. With pure functions, an elixir codebase is far simplest and maintainable, especially because functions usually don’t produce side effects, tests also are simple to develop too.

As I said most of the elixir function is pure functions and that’s awesome, but… A small part of functions has joined the dark side and became an impure function, and its return is not predictable, we’ll talk about it at the end of this text.

If you haven’t read yet, here is the previous posts of this series:

Anonymous Functions

To start our journey, let’s talk about anonymous functions the most basic way to create a function in elixir, create it is easy, you just need to use the fn keyword, followed by the function parameters and the body, ending with the end keyword.

For example, let’s build a function that sum 42 for the given number:

fn (number) -> number + 42 end

But you may be wondering “How do I call this function?”, as the name says anonymous function doesn’t have a name (isn’t bound to an identifier), and if we want to call it, first we need to store it on any variable.

sum = fn (number) -> number + 42 end

Depending of the other languages that you know, probably it’s new for you, but it’s very common to find in any functional language or languages that implements some functional features, usually with lambda keyword.

This example shows an important thing of Elixir, functions are first-class citizens, it basically means that functions are like other types in Elixir, and can be assigned to variables, pass as a parameter and much more. (It’s an important concept that comes from lambda calculus)

Backing to action, know we have our function assigned to sum variable, how do we call it? Simple:

sum.(2)
=> 44

In Elixir every function will return something and will be the value evaluated at the last line of the function.

A lot of functions in Elixir requires that you pass a function as a parameter, one of the most famous examples is the Enum.map/2, it receives an enumerable as the first param, and a function to be applied to each element as the second parameter, to use it, we use anonymous functions. (Functions that accept other functions as arguments are called “High Order Functions” and it’s very common in Elixir).

Enum.map([1, 2, 3, 4, 5], fn (number) -> 42 * number end)
[42, 84, 126, 168, 210]

If you want, Elixir provides a short way to create anonymous functions too, just use the & operator:

iex > hello = &(&1 + 42)
#Function<7.126501267/1 in :erl_eval.expr/5>
iex > hello.(12)
54

Your functions parameters will be available at &1, &2, &3 and so on…

Like with named functions, with anonymous functions we can do pattern matching at parameters too:

iex > hello = fn                               
... >   {:ok, name} -> "Hello #{name}"
... >   {_, message} -> "An error occured: #{error}"      
... > end                                    
#Function<7.126501267/1 in :erl_eval.expr/5>

And call this function passing the matching pattern:

iex > hello.({:ok, "Otavio"})
"Hello Otavio"
iex > hello.({:error, "Unexpected name"})
"An error occurerd: Unexpected name"

I have a great post about pattern matching too, just click here.

Interesting Point: Closures

Closures are how we call anonymous functions that contain a reference to variables outside of its scope, for example:

iex > name = "Otavio"
"Otavio"
iex > hello = fn -> IO.puts "Hello #{name}" end
#Function<21.126501267/0 in :erl_eval.expr/5>
iex > hello.()
Hello Otavio

But what will happen if we change the value of name and call it again?

...

iex > name = "Gabriela"
"Gabriela"
iex > hello.()         
Hello Otavio

This happens because Elixir holds the address of all out of the scope variables with the anonymous functions, and in this language data is immutable, so, it holds always the original value of name.

This behavior avoids side effects, and each call for our anonymous functions will produce the same result and bring to us the awesome pure functions that I talked about in the introduction.

Impure Functions

We’re not in the wonderland and some functions are not pure functions, a small part has joined the dark side and became impure functions, they are functions that the result is not always the same for a given parameter, they vary the result or produce side effects.

We have a few common examples in the programmer’s everyday life, external API calls, databases, and get user input.

iex > IO.gets "How much is 1 + 1?"
How much is 1 + 1?4
"4\n"
iex > IO.gets "How much is 1 + 1?"
How much is 1 + 1?2
"2\n"

In the previous example, the result of the function what different and its arguments was the same, this is a famous case of impure functions, but how to deal with them?

We can’t avoid this kind of function, the world is exact! But we have a lot of ways to deal with them and prevent unexpected results, but this is not in the scope of this post.

For now, focus on know that Elixir forces you to have a lot of pure functions, because everything in Elixir is immutable, but we’ll have contact if impure functions too, nothing is 100% perfect.

Conclusions

Functions are the core of every functional language (as the name says) and can help you making your code more readable and simple!

In this post, we learned about anonymous functions that will be used a lot in the future when dealing with topics like async tasks. Core Elixir’s concepts like immutable data and pure functions were studied too, and we learned about the existence of the dark side of the functions… impure functions.

Final thought

If you have any questions that I can help you with, please ask! Send an email (otaviopvaladares@gmail.com), pm me on my Twitter or comment on this post!

Follow my blog to get notified every new post:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s