Named functions
Inside a module, we can define functions with def/2
and private functions with defp/2
. A function defined with def/2
can be invoked from other modules while a private function can only be invoked locally.
defmodule Math do
def sum(a, b) do
do_sum(a, b)
end
defp do_sum(a, b) do
a + b
end
end
IO.puts Math.sum(1, 2) #=> 3
IO.puts Math.do_sum(1, 2) #=> ** (UndefinedFunctionError)
Function declarations also support guards and multiple clauses. If a function has several clauses, Elixir will try each clause until it finds one that matches. Here is an implementation of a function that checks if the given number is zero or not:
defmodule Math do
def zero?(0) do
true
end
def zero?(x) when is_number(x) do
false
end
end
IO.puts Math.zero?(0) #=> true
IO.puts Math.zero?(1) #=> false
IO.puts Math.zero?([1,2,3]) #=> ** (FunctionClauseError)
Giving an argument that does not match any of the clauses raises an error.
Similar to constructs like if
, named functions support both do:
and do
/end
block syntax, as we learned do
/end
is just a convenient syntax for the keyword list format. For example, we can edit math.exs
to look like this:
defmodule Math do
def zero?(0), do: true
def zero?(x) when is_number(x), do: false
end
And it will provide the same behaviour. You may use do:
for one-liners but always use do
/end
for functions spanning multiple lines.