Elixir is a lot like Ruby on the surface, but there are some big differences. It can be a struggle to know how to style your code. Thankfully niftynate put together a style guide. I found it very helpful and have reproduced it here in a slightly friendlier format. All of the original work can be found in their repository.
You should use two spaces spaces per indentation level. No hard tabs.
def some_function do
do_something
end
def some_function do
do_something
end
Use parentheses when you have arguments, no parentheses when you don't.
def some_function arg1, arg2 do
# body omitted
end
def some_function() do
# body omitted
end
def some_function(arg1, arg2) do
# body omitted
end
def some_function do
# body omitted
end
Never use do: for multi-line if/unless.
if some_condition, do:
# a line of code
# another line of code
# note no end in this block
if some_condition do
# some
# lines
# of code
end
Use do: for single-line if/unless
if some_condition, do:
# some_stuff
if some_condition, do: # some_stuff
Never use unless with else rewrite these with the positive case first.
unless success? do
IO.puts 'failure'
else
IO.puts 'success'
end
if success? do
IO.puts 'success'
else
IO.puts 'failure'
end
Always use true as the last condition of a cond statement.
cond do
1 + 2 == 5 ->
"Nope"
1 + 3 == 5 ->
"Uh, uh"
_ ->
"OK"
end
cond do
1 + 2 == 5 ->
"Nope"
1 + 3 == 5 ->
"Uh, uh"
true ->
"OK"
end
Never put a space between a function name and the opening parenthesis.
f (3 + 2) + 1
f 3 |> g # Parses as f (3 |> g)
f(3 + 2) + 1
f(3) |> g
Omit parentheses in macro calls when a do block is passed.
quote(do
foo
end)
quote do
foo
end
Optionally omit parentheses in function calls (outside a pipeline) when the last argument is a function expression.
Enum.reduce 1..10, 0, fn x, acc ->
x + acc
end
Enum.reduce(1..10, 0, fn x, acc ->
x + acc
end)
Use snake_case for atoms, functions and variables.
:"some atom"
:SomeAtom
:someAtom
someVar = 5
def someFunction do
...
end
def SomeFunction do
...
end
:some_atom
some_var = 5
def some_function do
...
end
Use CamelCase for modules (Keep acronyms like HTTP, RFC, XML uppercase).
defmodule Somemodule do
...
end
defmodule Some_Module do
...
end
defmodule SomeXml do
...
end
defmodule SomeModule do
...
end
defmodule SomeXML do
...
end
The names of predicate functions (a function that return a boolean value) should have a trailing question mark rather than a leading is_ or similar.
def cool?(var) do
# checks if var is cool
end
String.upcase(some_string) # Capitalize string
Use one module per file unless the module is only used internally by another module (such as a test). Use underscored file names for CamelCase module names.
# filename is some_module.ex
defmodule SomeModule do
end
Represent each level of nesting within a module name as a directory.
# filepath is parser/core/xml_parser.ex
defmodule Parser.Core.XMLParser do
end
Documentation in Elixir (when read either in iex with h or generated with ExDoc uses the Module Attributes @moduledoc and @doc
Always include an @moduledoc attribute the line after defmodule in your module.
defmodule SomeModule do
@moduledoc """
About the module
"""
...
end
defmodule AnotherModule do
use SomeModule
@moduledoc """
About the module
"""
...
end
defmodule SomeModule do
@moduledoc """
About the module
"""
...
end
Use @moduledoc false if you do not intend on documenting the module.
defmodule SomeModule do
@moduledoc false
...
end
Separate code after the @moduledoc with a new line.
defmodule SomeModule do
@moduledoc """
About the module
"""
use AnotherModule
end
defmodule SomeModule do
@moduledoc """
About the module
"""
use AnotherModule
end
Use heredocs with markdown for documentation.
defmodule SomeModule do
@moduledoc "About the module"
end
defmodule SomeModule do
@moduledoc """
About the module
Examples:
iex> SomeModule.some_function
:result
"""
end
defmodule SomeModule do
@moduledoc """
About the module
## Examples
iex> SomeModule.some_function
:result
"""
end
Match strings using the string concatenator rather than binary patterns:
<<"my"::utf8, _rest>> = "my string"
"my" <> _rest = "my string"
Avoid needless metaprogramming.
Suggested alternatives are styles that haven't been seen much in the community yet but might provide some value.
An atom can be used as a catch-all expression in a cond as it evaluates to a truthy value. Suggested atoms are :else or :otherwise .
cond do
1 + 2 == 5 ->
"Nope"
1 + 3 == 5 ->
"Uh, uh"
:else ->
"OK"
end
# is the same as
cond do
1 + 2 == 5 ->
"Nope"
1 + 3 == 5 ->
"Uh, uh"
true ->
"OK"
end