The Elixir Language: a Features Summary


The Elixir language
Overview the key features offered by the Elixir programming language and what are it's main use cases.

Introduction

Elixir is a general-purpose functional programming language with built-in support for concurrency and fault tolerance that shares many abstractions, libraries and tools with Erlang, a language created by Ericsson and used initially by telecom companies. It runs on BEAM, the Erlang Virtual Machine.

The first stable version was released on September 2014.

You may have heard of Elixir as being the programming language used by Phoenix, a rising web framework very loved by developers as demonstrated by many surveys such as the 2022 Stack Overflow Developer Survey, but what are the main features of this language ? and what is it used for ?

Elixir language features

  • Atoms: similar to symbols in Javascript. They are frequently used in Elixir with pattern matching as a way to handle function results (with the :ok and :error values for example).

  • Tuples: data structures that can be accessed by index (fast operation), for example {:ok, "hello"}. They are immutable by default as operations on them return new tuples.

  • Lists defined with square brackets are actually linked lists, for example: [1, 2, 3]. The ++ and -- operators are used to concatenate and subtract lists.

  • Keyword lists are defined like lists, but are primarily used to provide options to functions. The keys must be atoms and can be duplicate. When a keywords list is the last argument of a function, the brackets become optional: String.split("1 2 3", " ", trim: true)

  • Maps are key-value stores without any restrictions on keys. Example: map = %{:x => 1, 5 => :y}

  • Structs are special maps that provide type safety and default values: %User{name: "John", age: 30}

  • Pattern matching: can be used for destructuring complex data types. Works with tuples and lists. For example, after evaluating {:ok, result} = {:ok, 13}, the result variable will hold the value 13. You can use the pin operator to prevent a left side variable from being reassigned during pattern matching, like x in this example: [^x, 2, 3] = [1, 2, 3].

  • The case statement is similar to switch in other languages. You can pattern match values and execute the instructions of the matched pattern in the same control flow structure:

    Elixir case

  • The cond statement is similar to if / else if in other languages. If a true condition is not added and none of the conditions are matched, an error is raised:

    Elixir cond

  • Elixir also provides if, unless and else to check only one condition.

  • You can use guards in function definitions and case statements to define a condition for the execution of the function or the case pattern.

  • Enumerables and ranges are provided by Elixir along with functions to manipulate them, for example: Enum.map(1..3, fn x -> x * 2 end). Operations performed on enumerables using the Enum module are eager.

  • The pipe operator |> in Elixir is similar to the Unix | operator. It is used to simplify function calls by taking the output from the expression on its left side and passing it as the first argument to the function call on its right side: 1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(odd?) |> Enum.sum()

  • Streams are special enumerables that are lazy and composable:

    Elixir Streams

  • Protocols provide mechanisms to allow implementing additional behaviors for data types. They are similar to extension functions in other languages. They are defined with one protocol definition and multiple implementations for each data type.

  • Sigils are another way for developers to provide custom extensions to the Elixir language. They are defined with the tilde (~) character. Many predefined sigils are also provided such as Date:

    Elixir Sigils

  • Messaging in Elixir is based loosely on the Actor model. The Elixir processes are the main actors that communicate via message passing by using the send and receive constructs.

    Elixir messaging example

Elixir language uses

Distributed and scalable systems

Elixir does allow horizontal scaling with the lightweight threads, aka Elixir processes, that can run in the same machine or other machines of the same network.

Theses processes can communicate easily with each other, even if they are running on different machines on the same network.

Elixir will also try to maximize the CPU cores usage on the same machine, and thus offer better vertical scaling.

These properties makes it very convenient to build highly scalable distributed systems that require less resources compared to other languages.

High-availability applications

By default, Elixir processes are isolated. If one process fails, it will not affect other processes unless they are explicitly linked. This is why the most common way to handle failures in Elixir is by adopting the "fail fast" approach. Elixir provides mechanisms, called supervisors, that will instruct the system what to do when a process has failed. The try, catch, and rescue statements are less frequently used.

This provides the foundation to build fault tolerant systems that are highly available.

Web development

The Phoenix Framework allows building feature-rich and production ready web apps based on the Elixir language with less boilerplate code. One of the main advantages of using this framework include productivity thanks to the project generator and tasks tools.

It's follows an Model-View-Controller (MVC) architecture and comes with real time capabilities out-of-the-box.

You can build with Phoenix LiveView feature rich web apps with server-rendered views based on a declarative model.

Conclusion

The Elixir language provides many constructs that makes it easy to build fault-tolerant apps that scale.

It also allows building maintainable complex distributed systems with high productivity compared to other languages.

If you are interested in learning more about Elixir, you can follow the getting started guide.

You can also follow this installation guide if you want to try out the Phoenix Framework.


Soufiane Sakhi is an AWS Certified Solutions Architect – Associate and a professional full stack developer.