Appearance
Modules and functions
Source: Elixir guide, Modules and functions.
defmodule groups functions. The module name (an alias) starts with an uppercase letter, function names with lowercase or _.
elixir
defmodule Math do
def sum(a, b) do
a + b
end
end
Math.sum(1, 2) #=> 3Scripting
.ex files are compiled. .exs files are scripts. Elixir treats them the same, the difference is intent. Run one with elixir math.exs, or load it into a shell with iex math.exs.
Public and private
def is callable from other modules. defp is private to the module.
Clauses and guards
A function can have several clauses. Elixir tries them top to bottom and runs the first that matches. No match raises FunctionClauseError.
elixir
defmodule Math do
def zero?(0), do: true
def zero?(x) when is_integer(x), do: false
end
Math.zero?(0) #=> true
Math.zero?(1) #=> false
Math.zero?([1, 2, 3]) #=> ** (FunctionClauseError)A trailing ? conventionally means the function returns a boolean. do: is fine for one-liners, use do blocks for anything longer.
Default arguments
elixir
def join(a, b, sep \\ " "), do: a <> sep <> bThe default is evaluated each time it's used, not when the function is defined. With several clauses, declare defaults once in a body-less function head, which can't have patterns or guards:
elixir
def join(a, b, sep \\ " ")
def join(a, b, _sep) when b == "", do: a
def join(a, b, sep), do: a <> sep <> bAliases are atoms
A capitalized name like String is an alias that becomes an atom at compile time: String is :"Elixir.String". Modules on the Erlang VM are always atoms, and the Elixir. prefix keeps Elixir modules from clashing with Erlang ones. That is also how you call Erlang: :lists.flatten([1, [2], 3]).
Nesting
defmodule Foo do defmodule Bar do end end defines two independent modules, Foo and Foo.Bar. Inside Foo you can write Bar. Outside you need the full name or an alias. Foo doesn't have to exist before Foo.Bar.