DEV Community

Cover image for Elixir: A BEAM Machine
Alex Beasley
Alex Beasley

Posted on

Elixir: A BEAM Machine

Elixir has silently been revolutionizing the way we create scalable and maintainable applications. Born in 2011 and running on the BEAM (Björn's Erlang Abstract Machine), Elixir is a functional, concurrent, high level general purpose programming language. Elixir runs on the BEAM system which is used to implement the Erlang Open Telcom Platform (OTP) which is a set of libraries, middleware and tools that extend the Erlang programming language of the 80's.

Image description

Developed by José Valim, who also worked on the Ruby on Rails framework, Elixir was influenced by the large scale telecommunication system of the 1980's that was used for the massive demands of phone switching. The language was created to leverage the strengths of Erlang while providing a more modern and extensible syntax. It is particularly well suited for building fault tolerant systems with a focus on developer productivity within distributed systems.

Image description

Elixir is used by established institutions such as Discord, who uses the Elixir concurrency model and the Phoenix framework's ability to provide real time communication to handle the massive demand of concurrent users. Also used by Motorola to build resilience with the telecommunication systems, and Pinterest to scale up their real time notification systems. This involves handling large number of events and delivering notifications in a prompt efficient manner using asynchronous tasks and real time updates. The Elixir based Phoenix framework is responsible for thousands of full stack website applications. The Phoenix web framework leverages Elixir's concurrency model and OTP to provide a high performance, fail safe environment for budling applications.

Image description

According to this year's Stack Overflow developer survey (https://survey.stackoverflow.co/2023/#technology-most-popular-technologies) Elixir ranks at just 2.63% popularity ranked among other coding languages. Although it may not be the most popular language, its niche adoption with certain types of applications, particularly those that require multithread processing and low latency, has created a growing market.

Data Types

Similar to Ruby, Elixir is a dynamically typed language, which means that the variable types are determined at runtime rather than at compile time. Elixir offers a large amount of data types including Integers, Floats, Atoms, Ranges, Binaries, Lists, Maps and Tuples. Comments can be added using the pound sign "#" which helps us add pseudo code.

value = 42      # Integer
IO.puts value

value = "hello" # String
IO.puts value

value = :elixir # Atom
IO.puts value

# There is no maximum int size
my_int = 123
IO.puts "Integer #{is_integer(my_int)}"

# Floats have about 16 digit precision
my_float = 3.14159
IO.puts "Float #{is_float(my_float)}"

# An Atoms name is its value
IO.puts "Atom #{is_atom(:Pittsburgh)}"

# Use double quotes for spaces
:"New York"

# gets retrieves user input
# trim removes the newline
name = IO.gets("What is your name? ")
|> String.trim
Enter fullscreen mode Exit fullscreen mode

Once assigned, the values are immutable meaning they cannot be changed. Data types are bound by using the equal sign "=" and are constants. In Elixir, Input/Output statements are written using the IO keyword. There are a few different options for using them, IO.puts is like a console log and used for displaying a specific variable or statement. IO.inspect can be used to print a given term to the console for inspection. IO.gets can be used for prompting the user.

Atoms

Atoms play a crucial role in utilizing Elixir's expressiveness. They are literals that the name and value represent the same value. Atom's are immutable unique values, used as constants, labels or identifiers.

#this is how we would declare in JS
let test = "test"
:test
:'test'

{:error, reason} = {:error, "500 Internal Service Error"}
reason # "500 Internal Service Error"

{:ok, msg} = {:ok, "status 200 ok"}
msg # "status 200 ok"

def handle_resut(:ok), do: "status 200 ok"
def handle_result(:error), do: "500 Internal Service Error"
IO.puts handle_result(:ok) #status 200 ok
IO.puts handle_result(:error) #500 Internal Service Error
Enter fullscreen mode Exit fullscreen mode

Atoms are declared using a color ":" and can include letters, digits and numbers. Most commonly used in pattern matching to make code more expressive and readable. For the purpose of pattern matching we use Tuples. Tuples can hold 2 to 4 values and are not meant for enumeration or cycling like list with pattern matching.

Maps

Maps are similar to JavaScript objects and are the go to key-value structure in Elixir. Maps do not impose any restrictions on the key type. Anything can be a key in a map.

# Creating a map with key-value pairs
user = %{name: "Bob", age: 30, city: "New Orleans"}

# Accessing values from a map
name = user[:name]
IO.puts "User's name is #{name}" #User's name is Bob

# Updating values in a map
updated_user = Map.put(user, :age, 31)
IO.inspect updated_user 
#name: "Bob", age: 31, city: "New Orleans"

# Adding key-value pairs to a map
new_user = %{user | city: "Baton Rouge", email: "bob@gmail.com"}
IO.inspect new_user
#name: "Bob", age: 31, city: "Baton Rouge" email: "bob@gmail.com"
Enter fullscreen mode Exit fullscreen mode

Maps are created using the %{} syntax and can provide efficient key-based access and manipulation. Their flexibility and access make them invaluable for handling complex data structures.

Functions

Functions are defined using the "def" keyword. This keyword will signal the beginning of defining a function, you can then include the function name and it's different parameters.

#when the argument is the atom :world
def greet(:world), do: IO.puts "Hello, World!"
#any other argument
def greet(name), do: IO.puts "Hello, #{name}!

greet("Alex") 
#Hello, Alex!
greet(:world)
#Hello, World!
greet("Bob")
#Hello, Bob!

Enter fullscreen mode Exit fullscreen mode

Functions can also include pattern matching, allowing us to define multiple clauses for the same function name, making code more expressive, and allowing us to change the functions behavior depending on it's inputs.

defmodule Math do
  def add(a, b) do
    a + b
  end

  def add([head | tail]) do
    add(tail, acc + head)
  end
end
Enter fullscreen mode Exit fullscreen mode

This example allows us to add multiple clauses onto the add function, enabling us to use list or basic integers.

In conclusion, Elixir was born out of a desire to combine the reliability of Erlang with a more modern, developer friendly syntax. The phoenix design framework has become a go-to choice for building real-time web apps with dynamic typing, metaprogramming capabilities and code maintainability. As more companies adopt it for various use cases, the Elixir continues to grow providing a supporting community and a rich set of libraries.

Sources:
https://elixir-lang.org/docs.html
https://www.newthinktank.com/2017/04/learn-elixir-one-video/
https://en.wikipedia.org/wiki/Elixir_(programming_language)

Top comments (1)

Collapse
 
aaronblondeau profile image
aaronblondeau

I somewhat randomly chose Elixir as the language I should learn in 2024. I have really been enjoying it so far. Thanks for the quick overview and background on it!