Introduction to Elixir

What is Elixir?

Elixir is a dynamic, functional programming language designed for building scalable and maintainable applications. It runs on the Erlang VM (BEAM), known for creating low-latency, distributed, and fault-tolerant systems.

Key Features

  • Functional: Immutable data structures, first-class functions, pattern matching
  • Concurrent: Lightweight processes (not OS threads) - spawn millions easily
  • Fault-tolerant: "Let it crash" philosophy with supervisor trees
  • Scalable: Distributed by design, runs on multiple nodes
  • Productive: Modern syntax, powerful metaprogramming, excellent tooling
  • Interactive: REPL (IEx) for rapid development and debugging

History

  • Created by José Valim in 2011
  • Built on Erlang VM (created in 1986 by Ericsson)
  • Designed to address productivity while keeping Erlang's strengths
  • Used by Discord, Pinterest, Bleacher Report, Financial Times, and more

Installation

asdf allows you to manage multiple runtime versions.

# Install asdf (visit asdf-vm.com for OS-specific instructions)

# Add Erlang and Elixir plugins
asdf plugin add erlang
asdf plugin add elixir

# Install latest versions
asdf install erlang latest
asdf install elixir latest

# Set global versions
asdf global erlang <version>
asdf global elixir <version>

macOS

# Using Homebrew
brew install elixir

Ubuntu/Debian

# Add Erlang Solutions repo
wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb
sudo dpkg -i erlang-solutions_2.0_all.deb

# Install
sudo apt-get update
sudo apt-get install elixir

Windows

Download installer from elixir-lang.org

Verify Installation

elixir --version

You should see output like:

Erlang/OTP 26 [erts-14.2.1] [...]

Elixir 1.16.0 (compiled with Erlang/OTP 26)

Your First Elixir Program

Option 1: Script File

Create a file hello.exs:

IO.puts("Hello, World!")

Run it:

elixir hello.exs

Output:

Hello, World!

Option 2: Interactive Shell (IEx)

IEx is Elixir's interactive shell - think Python's REPL or Node's console.

iex

Try some commands:

iex> IO.puts("Hello, World!")
Hello, World!
:ok

iex> 1 + 2
3

iex> "hello" <> " " <> "world"
"hello world"

iex> String.upcase("elixir")
"ELIXIR"

IEx Tips

# Get help
iex> h String.upcase

# Autocomplete - press Tab
iex> String.up<TAB>

# Multiline input - use \
iex> 1 + \
...> 2
3

# Get type information
iex> i "hello"
# Shows detailed info about the string

# Previous result with `v`
iex> 1 + 2
3
iex> v()
3
iex> v() * 2
6

# Exit IEx
iex> exit  # or Ctrl+C twice

Basic Syntax Overview

Comments

# This is a single-line comment

# There are no multi-line comments in Elixir
# Just use multiple single-line comments

Basic Types

# Integer
42

# Float
3.14

# Boolean
true
false

# Atom (like Ruby symbols or enum values)
:ok
:error
:hello

# String (UTF-8)
"Hello, World!"

# List
[1, 2, 3]

# Tuple
{:ok, "result"}

# Map
%{name: "Alice", age: 30}

Basic Operations

# Arithmetic
iex> 1 + 2
3
iex> 10 - 5
5
iex> 3 * 4
12
iex> 10 / 2
5.0  # Always returns float

iex> div(10, 3)  # Integer division
3
iex> rem(10, 3)  # Remainder
1

# String concatenation
iex> "Hello" <> " " <> "World"
"Hello World"

# String interpolation
iex> name = "Alice"
"Alice"
iex> "Hello, #{name}!"
"Hello, Alice!"

# Boolean operators
iex> true and false
false
iex> true or false
true
iex> not true
false

# Comparison
iex> 1 == 1
true
iex> 1 != 2
true
iex> 1 < 2
true
iex> 1 >= 1
true

# Strict equality (checks type too)
iex> 1 == 1.0   # true (values are equal)
true
iex> 1 === 1.0  # false (different types)
false

Running Elixir Code

Three Ways to Execute

MethodUse CaseCommand
ScriptRun a .exs fileelixir script.exs
IExInteractive explorationiex
Mix ProjectFull applicationmix run

Script Files

Elixir uses two file extensions:

  • .exs - Elixir Script (interpreted, not compiled)
  • .ex - Elixir source (compiled into .beam files)

For learning, use .exs scripts:

# calculate.exs
defmodule Calculator do
  def add(a, b), do: a + b
  def multiply(a, b), do: a * b
end

IO.puts("3 + 4 = #{Calculator.add(3, 4)}")
IO.puts("3 * 4 = #{Calculator.multiply(3, 4)}")

Run:

elixir calculate.exs

Output:

3 + 4 = 7
3 * 4 = 12

Loading Code in IEx

# Load a file into IEx
iex> c "calculate.exs"
[Calculator]

# Now you can use the module
iex> Calculator.add(5, 3)
8

Your First Module

# greeter.exs
defmodule Greeter do
  def hello(name) do
    "Hello, #{name}!"
  end
  
  def goodbye(name) do
    "Goodbye, #{name}!"
  end
end

# Call the functions
IO.puts Greeter.hello("World")
IO.puts Greeter.goodbye("World")

Run:

elixir greeter.exs

Output:

Hello, World!
Goodbye, World!

Elixir Philosophy

1. Let It Crash

Unlike traditional error handling, Elixir embraces failures:

# Instead of defensive programming everywhere
# Let processes crash and supervisors restart them
# This leads to cleaner, more maintainable code

2. Immutability

All data is immutable - no variables change:

list = [1, 2, 3]
new_list = [0 | list]  # Creates new list: [0, 1, 2, 3]
# Original list unchanged: [1, 2, 3]

3. Pattern Matching

Assignment is actually pattern matching:

{:ok, result} = {:ok, 42}
# result is now 42

{:ok, result} = {:error, "failed"}
# ** (MatchError) - pattern doesn't match!

4. Transformation Pipeline

Data flows through transformations:

"hello world"
|> String.upcase()
|> String.split()
# => ["HELLO", "WORLD"]

Common Gotchas for Beginners

1. Variables Don't Vary (Much)

x = 1
x = 2  # This is actually rebinding, not mutation
# The original value 1 still exists elsewhere

2. Division Returns Float

10 / 2   # => 5.0 (not 5)
div(10, 2)  # => 5 (integer division)

3. Atoms Are Not Strings

:hello != "hello"  # Different types

4. Lists Are Linked Lists

# Fast operations
[0 | list]  # Prepend: O(1)

# Slow operations
list ++ [4]  # Append: O(n)
length(list)  # Length: O(n)

# Use Enum.count/1 for any enumerable

5. Parentheses Are Optional (But Use Them)

# Both work
String.upcase("hello")
String.upcase "hello"

# But be consistent (use parentheses for clarity)

Next Steps

Now that you have Elixir installed and understand the basics, you're ready to dive into:

  1. Variables and types - Deep dive into Elixir's type system
  2. Pattern matching - The secret sauce of Elixir
  3. Functions - First-class functions and function clauses
  4. Collections - Lists, tuples, maps, and how to work with them

Continue to 02-basics.md to learn about variables, types, and pattern matching in depth.

Exercise

Try these in IEx to get comfortable:

  1. Calculate the area of a circle with radius 5 (π * r²)
  2. Create a string with your name and use String.length/1 to count characters
  3. Create a list [1, 2, 3] and prepend 0 to it
  4. Use string interpolation to create "Hello, #{your_name}!"
  5. Try using the pipe operator: "HELLO" |> String.downcase() |> String.reverse()
# Solutions
iex> 3.14159 * 5 * 5
78.53975

iex> name = "Alice"
"Alice"
iex> String.length(name)
5

iex> [0 | [1, 2, 3]]
[0, 1, 2, 3]

iex> "Hello, #{name}!"
"Hello, Alice!"

iex> "HELLO" |> String.downcase() |> String.reverse()
"olleh"