Elixir is a functional, concurrent language that runs on the Erlang Virtual Machine (BEAM). It is designed for reliability, scalability, and maintainability.

What Makes Elixir Unique?

  • Runs on the BEAM: Inherits lightweight process model, preemptive scheduling, and fault tolerance from Erlang.
  • Immutability: All data is immutable by default.
  • Pattern Matching: Used extensively for variable assignment, function definitions, and control flow.
  • Pipelines: The |> operator allows chaining of function calls in a readable way.
  • First-Class Functions: Functions can be passed around as values.
  • Metaprogramming: Macros allow you to extend the language.

Basic Syntax

Variables and Immutability

x = 1
x = 2  # This is allowed; x is rebound, not mutated

Pattern Matching

{a, b} = {1, 2}  # a = 1, b = 2
 
# Matching in function arguments
defmodule Math do
  def add({a, b}), do: a + b
end
Math.add({3, 4})  # => 7

Anonymous Functions

add = fn a, b -> a + b end
add.(1, 2)  # => 3

The Pipe Operator (|>)

"hello"
|> String.upcase()
|> String.reverse()
# => "OLLEH"

Control Flow

if true do
  "yes"
else
  "no"
end
 
case {1, 2, 3} do
  {4, 5, 6} -> "no match"
  {1, x, 3} -> "matched: #{x}"
end

Recursion (No Loops)

defmodule Rec do
  def sum([]), do: 0
  def sum([h | t]), do: h + sum(t)
end
Rec.sum([1, 2, 3])  # => 6

Concurrency and the BEAM

Processes

  • Elixir processes are lightweight and managed by the BEAM, not OS threads.
  • Processes are isolated and communicate via message passing.
spawn(fn -> IO.puts("Hello from a process") end)

Message Passing

pid = spawn(fn ->
  receive do
    {:hello, msg} -> IO.puts(msg)
  end
end)
 
send(pid, {:hello, "Hi there!"})

Fault Tolerance

  • “Let it crash” philosophy: processes are supervised and can be restarted automatically.
defmodule Worker do
  def start do
    spawn(fn -> loop() end)
  end
 
  defp loop do
    receive do
      :crash -> exit(:error)
      msg -> IO.inspect(msg)
    end
    loop()
  end
end

Metaprogramming

  • Macros allow you to write code that generates code.
defmodule MyMacro do
  defmacro say_hello do
    quote do
      IO.puts("Hello from macro!")
    end
  end
end
 
defmodule Test do
  require MyMacro
  MyMacro.say_hello()
end

Summary Table: Elixir vs. Other Languages

FeatureElixir (on BEAM)Typical OOP Language
Data MutabilityImmutableMutable by default
Concurrency ModelActor (processes, BEAM)Threads, async/await
Pattern MatchingExtensiveLimited (e.g., switch)
MetaprogrammingMacros (hygienic)Reflection, templates
Error Handling”Let it crash”, supervisorsExceptions, try/catch