Skip to content

Elixir Functions — Named Functions, Anonymous Functions, and Captures

DodaTech Updated 2026-06-29 2 min read

In this tutorial, you will learn about Elixir Functions. We cover key concepts, practical examples, and best practices to help you master this topic.

Functions are the building blocks of Elixir programs. The language offers multiple ways to define and use functions — from named functions in modules to anonymous functions and the concise capture operator.

In this tutorial, you'll learn every form of function in Elixir and when to use each.

What You'll Learn

  • Named functions with def/defp
  • Function arity and multiple clauses
  • Default arguments
  • Anonymous functions (fn)
  • The capture operator (&)
  • Pattern matching in parameters
  • Guards

Named Functions

defmodule Greeter do
  # Public function
  def hello(name) do
    "Hello, #{name}!"
  end

  # Private function
  defp format_name(name) do
    String.trim(name)
  end

  # One-liner (do: syntax)
  def greet(name), do: hello(format_name(name))
end

IO.puts(Greeter.hello("Alice"))  # => Hello, Alice!

Multiple Clauses (Pattern Matching)

defmodule Math do
  # Multiple function heads — Elixir tries them in order
  def sum([]), do: 0
  def sum([head | tail]), do: head + sum(tail)

  # Different arities are different functions
  def area({:circle, r}), do: :math.pi() * r * r
  def area({:rectangle, w, h}), do: w * h
  def area({:triangle, b, h}), do: b * h / 2
end

IO.puts(Math.sum([1, 2, 3, 4]))  # => 10
IO.puts(Math.area({:circle, 5}))  # => 78.5398...

Default Arguments

defmodule Config do
  def create_server(host \ "localhost", port \ 8080) do
    "#{host}:#{port}"
  end
end

IO.puts(Config.create_server())            # => localhost:8080
IO.puts(Config.create_server("0.0.0.0"))   # => 0.0.0.0:8080
IO.puts(Config.create_server("0.0.0.0", 443))  # => 0.0.0.0:443

Anonymous Functions

# Basic anonymous function
square = fn x -> x * x end
IO.puts(square.(5))  # => 25  (NOTE: dot required!)

# Multiple clauses
describe = fn
  {:ok, value} -> "Success: #{value}"
  {:error, reason} -> "Error: #{reason}"
  _ -> "Unknown"
end

IO.puts(describe.({:ok, "data"}))  # => Success: data

# Multiple parameters
add = fn a, b -> a + b end
IO.puts(add.(3, 4))  # => 7

Capture Operator

The & operator creates anonymous functions concisely:

# Equivalent to fn x -> x * 2 end
double = &(&1 * 2)
IO.puts(double.(5))  # => 10

# Capture named function
Enum.map([1, 2, 3], &Math.sum/1)  # Won't work (sum expects list)
# But this works:
Enum.map([1, 2, 3], &(&1 * 2))  # => [2, 4, 6]

# Named function capture
strings = ["hello", "world"]
Enum.map(strings, &String.upcase/1)  # => ["HELLO", "WORLD"]

# Pipes and captures
[1, 2, 3]
|> Enum.map(&(&1 * 3))
|> Enum.filter(&(&1 > 5))
|> IO.inspect()  # => [6, 9]

Practice Questions

  1. Write a module with a function fib/1 using multiple clauses (0 → 0, 1 → 1, n → fib(n-1) + fib(n-2)).

  2. Create an anonymous function that validates email format.

  3. Use the capture operator to filter a list of numbers keeping only evens.

  4. Write a function with default arguments that generates a connection string.

  5. Use pattern matching in function heads to handle different map shapes.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro