0Pricing
Elixir & Phoenix: Scalable Backend Development · Lesson

Pattern Matching and Control Flow

Master Elixir's powerful pattern matching feature and essential control flow constructs like `if`, `case`, and `cond`.

Pattern Matching and Control Flow is a free Elixir & Phoenix: Scalable Backend Development lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Elixir & Phoenix: Scalable Backend Development learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Intro to Pattern Matching

Pattern matching is the heart of Elixir. Here = is a match operator, not assignment — it makes the left side equal the right.

Basic Variable Matching

The simplest match binds an unbound variable to a value. If it is already bound, Elixir instead checks that the two sides actually match.

defmodule BasicMatchDemo do
  def run do
    # 'a' is unbound, so it's assigned 10
    a = 10
    IO.puts "a is: #{a}"

    # 'b' is unbound, so it's assigned 20
    b = 20
    IO.puts "b is: #{b}"

    # This matches 'a' to the value of 'b' (20)
    # 'a' is re-bound to 20
    a = b
    IO.puts "After a = b, a is: #{a}"
  end
end

BasicMatchDemo.run()

Matching with Literals

Put a literal on the left and the match becomes an assertion: it succeeds only if both sides are equal, otherwise it raises. Handy for validation.

defmodule LiteralMatchDemo do
  def run do
    # This matches because 1 is equal to 1
    1 = 1
    IO.puts "1 = 1 matched successfully!"

    # This matches because 'hello' is equal to 'hello'
    "hello" = "hello"
    IO.puts "'hello' = 'hello' matched successfully!"

    # If you uncomment the line below, it will cause a MatchError
    # 1 = 2
    # IO.puts "This line would not be reached if 1 = 2 failed"
  end
end

LiteralMatchDemo.run()

Deconstructing Tuples

Matching shines on tuples — deconstruct them straight into variables, which is exactly how you unpack {:ok, value} results.

defmodule TupleMatchDemo do
  def run do
    # Match a tuple to extract its elements
    {:person, name, age} = {:person, "Alice", 30}
    IO.puts "Name: #{name}, Age: #{age}"

    # Match a common result tuple
    {:ok, data} = {:ok, "User fetched successfully"}
    IO.puts "Status: ok, Data: #{data}"

    # If you uncomment the line below, it will cause a MatchError
    # {:error, reason} = {:ok, "Success"}
  end
end

TupleMatchDemo.run()

Deconstructing Lists

Deconstruct lists with the [head | tail] pattern: head is the first element, tail the rest. Use _ for parts you do not care about.

defmodule ListMatchDemo do
  def run do
    list = [1, 2, 3, 4, 5]

    # Match head and tail
    [head | tail] = list
    IO.puts "Head: #{head}, Tail: #{inspect tail}"

    # Match specific elements
    [first, second, third | _rest] = list
    IO.puts "First: #{first}, Second: #{second}, Third: #{third}"

    # Match an empty list
    [] = []
    IO.puts "Empty list matched!"
  end
end

ListMatchDemo.run()

The Pin Operator (^)

The pin operator ^ says "do not rebind — match against this variable's current value" instead. Great for asserting equality.

defmodule PinOperatorDemo do
  def run do
    value_a = 10
    value_b = 10

    # This uses the current value of value_a (10) to match against value_b
    # It succeeds because 10 matches 10
    ^value_a = value_b
    IO.puts "Match successful: value_a = #{value_a}, value_b = #{value_b}"

    value_c = 5

    # If you uncomment the line below, it will cause a MatchError
    # because ^value_a (10) is not equal to value_c (5)
    # ^value_a = value_c
    # IO.puts "This line would not be reached if ^value_a = value_c failed"
  end
end

PinOperatorDemo.run()

Simple Conditionals: if/unless

For simple branches use if and its mirror unless, each with an optional else. The cleanest tool for one true/false condition.

defmodule IfUnlessDemo do
  def run do
    number = 7

    if number > 5 do
      IO.puts "Number is greater than 5"
    else
      IO.puts "Number is 5 or less"
    end

    unless rem(number, 2) == 0 do
      IO.puts "Number is odd"
    else
      IO.puts "Number is even"
    end
  end
end

IfUnlessDemo.run()

Handling Multiple Patterns with case

The case expression matches one value against several patterns and runs the first that fits — pattern matching as control flow.

defmodule CaseExpressionDemo do
  def run do
    status = {:ok, "Data loaded"}

    case status do
      {:ok, message} ->
        IO.puts "Success: #{message}"
      {:error, reason} ->
        IO.puts "Failed: #{reason}"
      _ ->
        IO.puts "Unknown status"
    end

    # Another example with a simple value
    grade = "B"
    case grade do
      "A" -> IO.puts "Excellent!"
      "B" -> IO.puts "Good job!"
      _ -> IO.puts "Keep trying!"
    end
  end
end

CaseExpressionDemo.run()

Multiple Conditions with cond

When you have many boolean checks (an if/else-if chain elsewhere), cond runs the first clause whose condition is true.

defmodule CondExpressionDemo do
  def run do
    score = 85

    cond do
      score >= 90 -> IO.puts "Grade: A"
      score >= 80 -> IO.puts "Grade: B"
      score >= 70 -> IO.puts "Grade: C"
      true -> IO.puts "Grade: D or lower" # The 'true' clause acts as a catch-all
    end

    temperature = 25
    cond do
      temperature > 30 -> IO.puts "It's hot!"
      temperature > 20 -> IO.puts "It's warm."
      true -> IO.puts "It's cool."
    end
  end
end

CondExpressionDemo.run()

Pattern Matching Challenge

Consider the following Elixir code snippet:

data = ["apple", {:fruit, "banana"}, "cherry"]
[first, {:fruit, second}, _] = data

What will be the final values of the variables first and second after this code executes?

Recap: Pattern Matching & Control

Recap: = matches, you deconstruct tuples and lists, ^ pins a value, and if/case/cond drive your control flow.

Frequently asked questions

Is the “Pattern Matching and Control Flow” lesson free?

Yes — the full text of “Pattern Matching and Control Flow” is free to read here on the web, and the Elixir & Phoenix: Scalable Backend Development course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Elixir & Phoenix: Scalable Backend Development course, upgrade to CoddyKit PRO.

What will I learn in “Pattern Matching and Control Flow”?

Master Elixir's powerful pattern matching feature and essential control flow constructs like `if`, `case`, and `cond`. You practise Elixir & Phoenix: Scalable Backend Development with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Elixir & Phoenix: Scalable Backend Development?

No prior experience is required. Elixir & Phoenix: Scalable Backend Development on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Pattern Matching and Control Flow” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Elixir & Phoenix: Scalable Backend Development lesson?

Yes. Every Elixir & Phoenix: Scalable Backend Development lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Introduction to Elixir Language
  2. Basic Data Types and Operators
  3. Pattern Matching and Control Flow
  4. Strings, Binaries & Sigils in Elixir
← Back to Elixir & Phoenix: Scalable Backend Development