Modules & Named Functions

Clauses are tried top to bottom; first match wins.

8.1 Defining modules

defmodule Math do
  def sum(a, b), do: a + b          # public, keyword syntax

  def square(x) do                  # public, block syntax
    x * x
  end

  defp secret(x), do: x * 42        # private (only callable inside Math)
end

Math.sum(1, 2)
Math.square 4     # parentheses optional, but recommended

8.2 Multiple clauses & pattern matching

Clauses are tried top to bottom; first match wins.

defmodule Greeter do
  def hello(%{name: name}), do: "Hello, #{name}"
  def hello(name) when is_binary(name), do: "Hello, #{name}"
  def hello(_), do: "Hello, stranger"
end

8.3 Guards

Allowed in guards: comparison, boolean, arithmetic, in, type checks, abs, div, rem, length, map_size, tuple_size, elem, hd, tl, byte_size, is_map_key, binary_part, bitwise functions, and custom guards built with defguard.

Errors inside guards make the guard fail silently (no exception).

defmodule Number do
  def classify(n) when is_integer(n) and n < 0, do: :negative
  def classify(0), do: :zero
  def classify(n) when is_integer(n), do: :positive
  def classify(n) when is_float(n), do: :float
end
defmodule Guards do
  defguard is_even(n) when is_integer(n) and rem(n, 2) == 0
end
import Guards
def f(n) when is_even(n), do: :even

8.4 Default arguments

With multiple clauses, declare defaults in a function head:

defmodule Hi do
  def greet(name, greeting \\ "Hello"), do: "#{greeting}, #{name}"
end
Hi.greet("Ann")            # "Hello, Ann"
Hi.greet("Ann", "Hey")     # "Hey, Ann"
def join(a, b \\ nil, sep \\ " ")
def join(a, nil, _sep), do: a
def join(a, b, sep), do: a <> sep <> b

8.5 Naming conventions

Modules: CamelCase (MyApp.UserController).

Functions & variables: snake_case.

Predicate functions end in ? (empty?), guard-safe predicates start with is_.

Functions that raise end in ! (File.read!/1).

Unused variables start with _.

8.6 Nested modules

Module nesting is just naming: Shop.Cart is the atom :"Elixir.Shop.Cart".

defmodule Shop do
  defmodule Cart do
    def new, do: []
  end
end
Shop.Cart.new()

8.7 Function references & apply

apply(Math, :sum, [1, 2])
fun = &Math.sum/2
fun.(1, 2)
Kernel.function_exported?(Math, :sum, 2)