Modules and Functions

Elixir modules, named functions, anonymous functions, defaults, and guards

Modules

Modules group named functions. By convention, module names are CamelCase.

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

Math.add(1, 2)   # => 3

Nested modules

defmodule MyApp.User do
  defstruct name: nil, email: nil
end

# Equivalent to:
defmodule MyApp.User do ... end

Named functions

defmodule Greeter do
  # Single-line (do: syntax)
  def hello(name), do: "Hello, #{name}"

  # Multi-line (do/end block)
  def greet(name) do
    message = "Hi #{name}!"
    IO.puts(message)
    message
  end

  # Private function (only callable within the module)
  defp format(name), do: String.capitalize(name)
end

Default arguments

defmodule Http do
  def get(url, opts \\ []) do
    # opts defaults to []
  end

  # With defaults, you need a function head for multiple clauses
  def connect(host \\ "localhost", port \\ 4000)

  def connect(host, port) when is_binary(host) do
    # ...
  end
end

Guards

Guards extend pattern matching with additional checks:

defmodule Calculator do
  def divide(_, 0), do: {:error, "division by zero"}
  def divide(a, b) when is_number(a) and is_number(b), do: {:ok, a / b}

  def max(a, b) when a >= b, do: a
  def max(_, b), do: b
end

Allowed guard expressions

Only a subset of expressions are allowed in guards:

Anonymous functions

# Basic
square = fn x -> x * x end
square.(4)  # => 16

# Shorthand (& capture syntax)
add = &(&1 + &2)
add.(1, 2)  # => 3

# Capturing a named function
upcase = &String.upcase/1
upcase.("hello")  # => "HELLO"

# Closures (captures variables from outer scope)
defmodule Counter do
  def make do
    count = 0
    {fn -> count end, fn -> count = count + 1 end}
  end
end

Module attributes

defmodule Config do
  @default_port 4000
  @app_name "MyApp"

  # Accumulating attribute (appends to a list)
  Module.register_attribute(__MODULE__, :plugins, accumulate: true)
  @plugins :auth
  @plugins :logging

  def port, do: @default_port
  def name, do: @app_name
end

Common attributes: @moduledoc, @doc, @spec, @since, @deprecated.