basic language primitives, such as arithmetic operators, spawning of processes,
data type handling, and others
macros for control-flow and defining new functionality (modules, functions, and the like)
guard checks for augmenting pattern matching
You can invoke Kernel functions and macros anywhere in Elixir code
without the use of the Kernel. prefix since they have all been
automatically imported. For example, in IEx, you can call:
iex> is_number(13)true
If you don't want to import a function or macro from Kernel, use the :except
option and then list the function/macro by arity:
Elixir also has special forms that are always imported and
cannot be skipped. These are described in Kernel.SpecialForms.
The standard library
Kernel provides the basic capabilities the Elixir standard library
is built on top of. It is recommended to explore the standard library
for advanced functionality. Here are the main groups of modules in the
standard library (this list is not a complete reference, see the
documentation sidebar for all entries).
Built-in types
The following modules handle Elixir built-in data types:
Atom - literal constants with a name (true, false, and nil are atoms)
There are two data types without an accompanying module:
Bitstring - a sequence of bits, created with <<>>/1.
When the number of bits is divisible by 8, they are called binaries and can
be manipulated with Erlang's :binary module
Reference - a unique value in the runtime system, created with make_ref/0
Data types
Elixir also provides other data types that are built on top of the types
listed above. Some of them are:
Protocols add polymorphic dispatch to Elixir. They are contracts
implementable by data types. See Protocol for more information on
protocols. Elixir provides the following protocols in the standard library:
Enumerable - handles collections in Elixir. The Enum module
provides eager functions for working with collections, the Stream
module provides lazy functions
Inspect - converts data types into their programming language
representation
List.Chars - converts data types to their outside world
representation as charlists (non-programming based)
String.Chars - converts data types to their outside world
representation as strings (non-programming based)
Process-based and application-centric functionality
The following modules build on top of processes to provide concurrency,
fault-tolerance, and more.
Task.Supervisor - a supervisor for managing tasks exclusively
Supporting documents
Under the "Pages" section in sidebar you will find tutorials, guides,
and reference documents that outline Elixir semantics and behaviors
in more detail. Those are:
Compatibility and deprecations - lists
compatibility between every Elixir version and Erlang/OTP, release schema;
lists all deprecated functions, when they were deprecated and alternatives
Library guidelines - general guidelines, anti-patterns,
and rules for those writing libraries
This module includes the built-in guards used by Elixir developers.
They are a predefined set of functions and macros that augment pattern
matching, typically invoked after the when operator. For example:
defdrive(%User{age:age})whenage>=16do...end
The clause above will only be invoked if the user's age is more than
or equal to 16. Guards also support joining multiple conditions with
and and or. The whole guard is true if all guard expressions will
evaluate to true. A more complete introduction to guards is available
in the Patterns and guards page.
Truthy and falsy values
Besides the booleans true and false, Elixir has the
concept of a "truthy" or "falsy" value.
a value is truthy when it is neither false nor nil
a value is falsy when it is either false or nil
Elixir has functions, like and/2, that only work with
booleans, but also functions that work with these
truthy/falsy values, like &&/2 and !/1.
Structural comparison
The functions in this module perform structural comparison. This allows
different data types to be compared using comparison operators:
1<:an_atom
This is possible so Elixir developers can create collections, such as
dictionaries and ordered sets, that store a mixture of data types in them.
To understand why this matters, let's discuss the two types of comparisons
we find in software: structural and semantic.
Structural means we are comparing the underlying data structures and we often
want those operations to be as fast as possible, because it is used to power
several algorithms and data structures in the language. A semantic comparison
worries about what each data type represents. For example, semantically
speaking, it doesn't make sense to compare Time with Date.
One example that shows the differences between structural and semantic
comparisons are strings: "alien" sorts less than "office" ("alien" < "office")
but "álien" is greater than "office". This happens because < compares the
underlying bytes that form the string. If you were doing alphabetical listing,
you may want "álien" to also appear before "office".
This means comparisons in Elixir are structural, as it has the goal
of comparing data types as efficiently as possible to create flexible
and performant data structures. This distinction is specially important
for functions that provide ordering, such as >/2, </2, >=/2,
<=/2, min/2, and max/2. For example:
~D[2017-03-31]>~D[2017-04-01]
will return true because structural comparison compares the :day
field before :month or :year. Luckily, the Elixir compiler will
detect whenever comparing structs or whenever comparing code that is
either always true or false, and emit a warning accordingly.
In order to perform semantic comparisons, the relevant data-types
provide a compare/2 function, such as Date.compare/2:
The second argument is precisely the module to be used for semantic
comparison. Keeping this distinction is important, because if semantic
comparison was used by default for implementing data structures and
algorithms, they could become orders of magnitude slower!
Finally, note there is an overall structural sorting order, called
"Term Ordering", defined below. This order is provided for reference
purposes, it is not required for Elixir developers to know it by heart.
When comparing two numbers of different types (a number being either
an integer or a float), a conversion to the type with greater precision
will always occur, unless the comparison operator used is either ===/2
or !==/2. A float will be considered more precise than an integer, unless
the float is greater/less than +/-9007199254740992.0 respectively,
at which point all the significant figures of the float are to the left
of the decimal point. This behavior exists so that the comparison of large
numbers remains transitive.
The collection types are compared using the following rules:
Tuples are compared by size, then element by element.
Maps are compared by size, then by key-value pairs.
Lists are compared element by element.
Bitstrings are compared byte by byte, incomplete bytes are compared bit by bit.
Atoms are compared using their string value, codepoint by codepoint.
Examples
We can check the truthiness of a value by using the !/1
function twice.
Some of the functions described in this module are inlined by
the Elixir compiler into their Erlang counterparts in the
:erlang module.
Those functions are called BIFs (built-in internal functions)
in Erlang-land and they exhibit interesting properties, as some
of them are allowed in guards and others are used for compiler
optimizations.
Most of the inlined functions can be seen in effect when
capturing the function:
iex> &Kernel.is_atom/1&:erlang.is_atom/1
Those functions will be explicitly marked in their docs as
"inlined by the compiler".
Returns the node where the given argument is located.
The argument can be a PID, a reference, or a port.
If the local node is not alive, :nonode@nohost is returned.
This operator considers 1 and 1.0 to be equal. For match
comparison, use !==/2 instead.
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
Returns true if the two terms are not exactly equal.
See ===/2 for a definition of what is considered "exactly equal".
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
Returns true if left is less than or equal to right.
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
Equal to operator. Returns true if the two terms are equal.
This operator considers 1 and 1.0 to be equal. For stricter
semantics, use ===/2 instead.
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
The terms are only considered to be exactly equal if they
have the same value and are of the same type. For example,
1 == 1.0 returns true, but since they are of different
types, 1 === 1.0 returns false.
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
Returns true if left is more than or equal to right.
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
Returns the number of bytes needed to contain bitstring.
That is, if the number of bits in bitstring is not divisible by 8, the
resulting number of bytes will be rounded up (by excess). This operation
happens in constant time.
Returns the head of a list. Raises ArgumentError if the list is empty.
The head of a list is its first element.
It works with improper lists.
Allowed in guard tests. Inlined by the compiler.
Examples
iex> hd([1,2,3,4])1iex> hd([1|2])1
Giving it an empty list raises:
hd([])** (ArgumentError) argument error
left in right
(macro)
Membership operator.
Checks if the element on the left-hand side is a member of the
collection on the right-hand side.
Examples
iex> x=1iex> xin[1,2,3]true
This operator (which is a macro) simply translates to a call to
Enum.member?/2. The example above would translate to:
Enum.member?([1,2,3],x)
Elixir also supports left not in right, which evaluates to
not(left in right):
iex> x=1iex> xnotin[1,2,3]false
Guards
The in/2 operator (as well as not in) can be used in guard clauses as
long as the right-hand side is a range or a list.
If the right-hand side is a list, Elixir will expand the operator to a valid
guard expression which needs to check each value. For example:
whenxin[1,2,3]
translates to:
whenx===1orx===2orx===3
However, this construct will be inefficient for large lists. In such cases, it
is best to stop using guards and use a more appropriate data structure, such
as MapSet.
If the right-hand side is a range, a more efficient comparison check will be
done. For example:
whenxin1..1000
translates roughly to:
whenx>=1andx<=1000
AST considerations
left not in right is parsed by the compiler into the AST:
Returns true if term is a struct of name, otherwise returns false.
is_struct/2 does not check that name exists and is a valid struct.
If you want such validations, you must pattern match on the struct
instead, such as match?(%URI{}, arg).
The size of a map is the number of key-value pairs that the map contains.
This operation happens in constant time.
Allowed in guard tests. Inlined by the compiler.
Examples
iex> map_size(%{a:"foo",b:"bar"})2
max(first, second)
@spec max(first, second) :: first | second when first: term(), second: term()
Returns the biggest of the two given terms according to
their structural comparison.
If the terms compare equal, the first one is returned.
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
Allowed in guard tests. Inlined by the compiler.
Examples
iex> max(1,2)2iex> max("a","b")"b"
min(first, second)
@spec min(first, second) :: first | second when first: term(), second: term()
Returns the smallest of the two given terms according to
their structural comparison.
If the terms compare equal, the first one is returned.
This performs a structural comparison where all Elixir
terms can be compared with each other. See the "Structural
comparison" section
for more information.
Returns the node where the given argument is located.
The argument can be a PID, a reference, or a port.
If the local node is not alive, :nonode@nohost is returned.
Allowed in guard tests. Inlined by the compiler.
not value
@spec not true :: false
@spec not false :: true
Strictly boolean "not" operator.
value must be a boolean; if it's not, an ArgumentError exception is raised.
Allowed in guard tests. Inlined by the compiler.
Examples
iex> notfalsetrue
left or right
(macro)
Strictly boolean "or" operator.
If left is true, returns true, otherwise returns right.
Requires only the left operand to be a boolean since it short-circuits.
If the left operand is not a boolean, a BadBooleanError exception is
raised.
Allowed in guard tests.
Examples
iex> trueorfalsetrueiex> falseor4242iex> 42orfalse** (BadBooleanError) expected a boolean on left-side of "or", got: 42
Provides a short-circuit operator that evaluates and returns
the second expression only if the first one evaluates to a truthy value
(neither false nor nil). Returns the first expression
otherwise.
It takes two numbers for input. If both are integers and the right-hand
side (the exponent) is also greater than or equal to 0, then the result
will also be an integer. Otherwise it returns a float.
List concatenation operator. Concatenates a proper list and a term, returning a list.
The complexity of a ++ b is proportional to length(a), so avoid repeatedly
appending to lists of arbitrary length, for example, list ++ [element].
Instead, consider prepending via [element | rest] and then reversing.
If the right operand is not a proper list, it returns an improper list.
If the left operand is not a proper list, it raises ArgumentError.
If the left operand is an empty list, it returns the right operand.
Inlined by the compiler.
Examples
iex> [1]++[2,3][1,2,3]iex> ~c"foo"++~c"bar"~c"foobar"# a non-list on the right will return an improper list# with said element at the endiex> [1,2]++3[1,2|3]iex> [1,2]++{3,4}[1,2|{3,4}]# improper list on the right will return an improper listiex> [1]++[2|3][1,2|3]# empty list on the left will return the right operandiex> []++11
If first is less than last, the range will be increasing from
first to last. If first is equal to last, the range will contain
one element, which is the number itself.
If first is more than last, the range will be decreasing from first
to last, albeit this behavior is deprecated. Instead prefer to
explicitly list the step with first..last//-1.
Unlike Erlang, such attributes are not stored in the module by default since
it is common in Elixir to use custom attributes to store temporary data that
will be available at compile-time. Custom attributes may be configured to
behave closer to Erlang by using Module.register_attribute/3.
Prefixing module attributes
Libraries and frameworks should consider prefixing any
module attributes that are private by underscore, such as @_my_data,
so code completion tools do not show them on suggestions and prompts.
Finally, note that attributes can also be read inside functions:
It is important to note that reading an attribute takes a snapshot of
its current value. In other words, the value is read at compilation
time and not at runtime. Check the Module module for other functions
to manipulate module attributes.
Attention! Multiple references of the same attribute
As mentioned above, every time you read a module attribute, a snapshot
of its current value is taken. Therefore, if you are storing large
values inside module attributes (for example, embedding external files
in module attributes), you should avoid referencing the same attribute
multiple times. For example, don't do this:
In the above, each reference to @files may end-up with a complete
and individual copy of the whole @files module attribute. Instead,
reference the module attribute once in a private function:
Invokes the given anonymous function fun with the list of
arguments args.
If the number of arguments is known at compile time, prefer
fun.(arg_1, arg_2, ..., arg_n) as it is clearer than
apply(fun, [arg_1, arg_2, ..., arg_n]).
Invokes the given function from module with the list of
arguments args.
apply/3 is used to invoke functions where the module, function
name or arguments are defined dynamically at runtime. For this
reason, you can't invoke macros using apply/3, only functions.
If the number of arguments and the function name are known at compile time,
prefer module.function(arg_1, arg_2, ..., arg_n) as it is clearer than
apply(module, :function, [arg_1, arg_2, ..., arg_n]).
Returns a binary from the offset given by the start of the
range to the offset given by the end of the range.
If the start or end of the range are negative, they are converted
into positive indices based on the binary size. For example,
-1 means the last byte of the binary.
This is similar to binary_part/3 except that it works with ranges
and it is not allowed in guards.
This function works with bytes. For a slicing operation that
considers characters, see String.slice/2.
Returns a binary starting at the offset start and of the given size.
This is similar to binary_part/3 except that if start + size
is greater than the binary size, it automatically clips it to
the binary size instead of raising. Opposite to binary_part/3,
this function is not allowed in guards.
This function works with bytes. For a slicing operation that
considers characters, see String.slice/3.
The default debugging function prints additional debugging info when dealing with
pipelines. It prints the values at every "step" of the pipeline.
"Elixir is cool!"|>String.trim_trailing("!")|>String.split()|>List.first()|>dbg()#=> "Elixir"
The code above prints:
[my_file.ex:10:MyMod.my_fun/0]"Elixir is cool!"#=> "Elixir is cool!"|>String.trim_trailing("!")#=> "Elixir is cool"|>String.split()#=> ["Elixir", "is", "cool"]|>List.first()#=> "Elixir"
With no arguments, dbg() debugs information about the current binding. See binding/1.
dbg inside IEx
You can enable IEx to replace dbg with its IEx.pry/0 backend by calling:
$ iex --dbg pry
In such cases, dbg will start a pry session where you can interact with
the imports, aliases, and variables of the current environment at the location
of the dbg call.
If you call dbg at the end of a pipeline (using |>) within IEx, you are able
to go through each step of the pipeline one by one by entering "next" (or "n").
Note dbg only supports stepping for pipelines (in other words, it can only
step through the code it sees). For general stepping, you can set breakpoints
using IEx.break!/4.
One of the benefits of dbg/2 is that its debugging logic is configurable,
allowing tools to extend dbg with enhanced behaviour. This is done, for
example, by IEx which extends dbg with an interactive shell where you
can directly inspect and access values.
The debug function can be configured at compile time through the :dbg_callback
key of the :elixir application. The debug function must be a
{module, function, args} tuple. The function function in module will be
invoked with three arguments prepended to args:
The debug function is invoked at compile time and it must also return an AST.
The AST is expected to ultimately return the result of evaluating the debugged
expression.
# In config/config.exsconfig:elixir,:dbg_callback,{MyMod,:debug_fun,[:stdio]}
Default debug function
By default, the debug function we use is Macro.dbg/3. It just prints
information about the code to standard output and returns the value
returned by evaluating code. options are used to control how terms
are inspected. They are the same options accepted by inspect/2.
def(call, expr \\ nil)
(macro)
Defines a public function with the given name and body.
Examples
defmoduleFoododefbar,do::bazendFoo.bar()#=> :baz
A function that expects arguments can be defined as follows:
defmoduleFoododefsum(a,b)doa+bendend
In the example above, a sum/2 function is defined; this function receives
two arguments and returns their sum.
Default arguments
\\ is used to specify a default value for a parameter of a function. For
example:
The compiler translates this into multiple functions with different arities,
here MyMath.multiply_by/1 and MyMath.multiply_by/2, that represent cases when
arguments for parameters with default values are passed or not passed.
When defining a function with default arguments as well as multiple
explicitly declared clauses, you must write a function head that declares the
defaults. For example:
The difference between using Map and Keyword to store many
arguments is Keyword's keys:
must be atoms
can be given more than once
ordered, as specified by the developer
Function names
Function and variable names in Elixir must start with an underscore or a
Unicode letter that is not in uppercase or titlecase. They may continue
using a sequence of Unicode letters, numbers, and underscores. They may
end in ? or !. Elixir's Naming Conventions
suggest for function and variable names to be written in the snake_case
format.
rescue/catch/after/else
Function bodies support rescue, catch, after, and else as try/1
does (known as "implicit try"). For example, the following two functions are equivalent:
Defines a function that delegates to another module.
Functions defined with defdelegate/2 are public and can be invoked from
outside the module they're defined in, as if they were defined using def/2.
Therefore, defdelegate/2 is about extending the current module's public API.
If what you want is to invoke a function defined in another module without
using its full module name, then use alias/2 to shorten the module name or use
import/2 to be able to invoke the function without the module name altogether.
Delegation only works with functions; delegating macros is not supported.
Check def/2 for rules on naming and default arguments.
Options
:to - the module to dispatch to.
:as - the function to call on the target given in :to.
This parameter is optional and defaults to the name being
delegated (funs).
Exceptions are structs backed by a module that implements
the Exception behaviour. The Exception behaviour requires
two functions to be implemented:
exception/1 - receives the arguments given to raise/2
and returns the exception struct. The default implementation
accepts either a set of keyword arguments that is merged into
the struct or a string to be used as the exception's message.
message/1 - receives the exception struct and must return its
message. Most commonly exceptions have a message field which
by default is accessed by this function. However, if an exception
does not have a message field, this function must be explicitly
implemented.
The most common way to raise an exception is via raise/2:
defmoduleMyAppErrordodefexception[:message]endvalue=[:hello]raiseMyAppError,message:"did not get what was expected, got: #{inspect(value)}"
In many cases it is more convenient to pass the expected value to
raise/2 and generate the message in the Exception.exception/1 callback:
defmoduleMyAppErrordodefexception[:message]@impltruedefexception(value)domsg="did not get what was expected, got: #{inspect(value)}"%MyAppError{message:msg}endendraiseMyAppError,value
The example above shows the preferred strategy for customizing
exception messages.
Once defined, custom guards can be invoked within regular code or in
guards. The module that contains the custom guard must be required before usage.
Custom guards are defined by providing a valid guard expression to
the right-hand side of when. defguard will then expand and validate
the expressions as guards. defguard will raise at compile time if the
guard uses expressions that aren't allowed in guard clauses.
When defining your own guards, consider the
naming conventions
around boolean-returning guards.
Example
For example, to define a guard similar to Integer.is_even/1, you can write:
Behind the scenes, defguard will generate a macro which can be used
inside and outside of guards, preserving their respective semantics.
When invoked inside a guard, it behaves as if the right-hand side of
when is injected as part of the guard, replacing the custom guard
arguments by the expressions given as inputs.
When invoked outside of a guard, it preserves regular function calling
semantics with one caveat: all arguments are evaluated before invocation,
except arguments which are unused, which are then never evaluated.
Defines a private macro suitable for use in guard expressions.
It raises at compile time if the guard uses expressions that aren't
allowed in guard clauses,
and otherwise creates a private macro that can be used
both inside or outside guards in the current module.
When defining your own guards, consider the
naming conventions
around boolean-returning guards.
Similar to defmacrop/2, defguardp/1 must be defined before its use
in the current module.
Module names (and aliases) must start with an ASCII uppercase character which
may be followed by any ASCII letter, number, or underscore. Elixir's
Naming Conventions suggest for module names and aliases
to be written in the CamelCase format.
You can also use atoms as the module name, although they must only contain ASCII
characters.
Nesting
Nesting a module inside another module affects the name of the nested module:
defmoduleFoododefmoduleBardoendend
In the example above, two modules - Foo and Foo.Bar - are created.
When nesting, Elixir automatically creates an alias to the inner module,
allowing the second module Foo.Bar to be accessed as Bar in the same
lexical scope where it's defined (the Foo module). This only happens
if the nested module is defined via an alias.
If the Foo.Bar module is moved somewhere else, the references to Bar in
the Foo module need to be updated to the fully-qualified name (Foo.Bar) or
an alias has to be explicitly set in the Foo module with the help of
alias/2.
defmoduleFoo.Bardo# codeenddefmoduleFoodoaliasFoo.Bar# code here can refer to "Foo.Bar" as just "Bar"end
Dynamic names
Elixir module names can be dynamically generated. This is very
useful when working with macros. For instance, one could write:
Elixir will accept any module name as long as the expression passed as the
first argument to defmodule/2 evaluates to an atom.
Note that, when a dynamic name is used, Elixir won't nest the name under
the current module nor automatically set up an alias.
Reserved module names
If you attempt to define a module that already exists, you will get a
warning saying that a module has been redefined.
There are some modules that Elixir does not currently implement but it
may be implement in the future. Those modules are reserved and defining
them will result in a compilation error:
defmoduleAnydo# codeend** (CompileError) iex:1: module Any is reserved and cannot be defined
Elixir reserves the following module names: Elixir, Any, BitString,
PID, and Reference.
defoverridable(keywords_or_behaviour)
(macro)
Makes the given definitions in the current module overridable.
If the user defines a new function or macro with the same name
and arity, then the overridable ones are discarded. Otherwise, the
original definitions are used.
It is possible for the overridden definition to have a different
visibility than the original: a public function can be overridden
by a private function and vice-versa. Macros cannot be overridden
as functions and vice-versa.
As seen as in the example above, super can be used to call the default
implementation.
Example with behaviour
defoverridable is commonly used with behaviours. The behaviours use
@callback definitions to define the general module API and the
__using__ callback is used to define default implementations of
functions, which can then be overridable.
For convenience, you can pass a behaviour to defoverridable and it
will mark all of the callbacks in the behaviour as overridable:
When defining behaviours, a general rule of thumb is to define narrow
behaviours, with the minimum amount of callbacks, to facilitate maintenance
over time. Fewer callbacks minimize the points of contact between different
parts of the system and reduces the risk of breaking changes and of different
implementations having inconsistent behaviour. However, when using defoverridable
with behaviours, you may accidentally define broad interfaces as all default
behaviour is provided via defoverridable. Furthermore, defoverridable
necessarily relies on meta-programming, which complicates debugging. super is
also hard to troubleshoot, as it by definition relies on calling an implicitly
defined function.
A possible alternative to defoverridable is to use optional callbacks and
move the default implementation to the caller. Then you can check if a callback
exists via Code.ensure_loaded?/1 and function_exported?/3. For instance,
in the example above, imagine there is a module that calls the test/2 function.
This module could be defined as such:
The downside of the above code is that it must call Code.ensure_loaded?/1 and
function_exported?/3 on every invocation of the behaviour, which may impact
runtime performance. For this reason, this approach works best when the behaviour
has an entry point, such as a init callback (as seen in GenServer), which you
invoke once to guarantee the module is loaded, and from that moment, you only need
to perform function_exported?/3 checks.
If using defoverridable, avoid relying on super to trigger the default
behaviour, suggesting users to invoke well-defined APIs instead.
defp(call, expr \\ nil)
(macro)
Defines a private function with the given name and body.
Private functions are only accessible from within the module in which they are
defined. Trying to access a private function from outside the module it's
defined in results in an UndefinedFunctionError exception.
A struct is a tagged map that allows developers to provide
default values for keys, tags to be used in polymorphic
dispatches and compile time assertions.
It is only possible to define a struct per module, as the
struct is tied to the module itself.
Examples
defmoduleUserdodefstructname:nil,age:nilend
Struct fields are evaluated at compile-time, which allows
them to be dynamic. In the example below, 10 + 11 is
evaluated at compile-time and the age field is stored
with value 21:
defmoduleUserdodefstructname:nil,age:10+11end
The fields argument is usually a keyword list with field names
as atom keys and default values as corresponding values. defstruct/1
also supports a list of atoms as its argument: in that case, the atoms
in the list will be used as the struct's field names and they will all
default to nil.
Add documentation to a struct with the @doc attribute, like a function.
defmodulePostdo@doc"A post. The content should be valid Markdown."defstruct[:title,:content,:author]end
Once a struct is defined, it is possible to create them as follows:
%Post{title:"Hello world!"}
For more information on creating, updating, and pattern matching on
structs, please check %/2.
Deriving
Although structs are maps, by default structs do not implement
any of the protocols implemented for maps. For example, attempting
to use a protocol with the User struct leads to an error:
john=%User{name:"John"}MyProtocol.call(john)** (Protocol.UndefinedError) protocol MyProtocol not implemented for User (a struct)
defstruct/1, however, allows protocol implementations to be
derived. This can be done by defining a @derive attribute as a
list before invoking defstruct/1:
defmoduleUserdo@deriveMyProtocoldefstructname:nil,age:nilendMyProtocol.call(john)# it works!
A common example is to @derive the Inspect protocol to hide certain fields
when the struct is printed:
For each protocol in @derive, Elixir will verify if the protocol
has implemented the Protocol.__deriving__/2 callback. If so,
the callback will be invoked and it should define the implementation
module. Otherwise an implementation that simply points to the Any
implementation is automatically derived. For more information, see
Protocol.derive/3.
Enforcing keys
When building a struct, Elixir will automatically guarantee all keys
belong to the struct:
%User{name:"john",unknown::key}** (KeyError) key :unknown not found in: %User{age: 21, name: nil}
Elixir also allows developers to enforce that certain keys must always be
given when building the struct:
Now trying to build a struct without the name key will fail:
%User{age:21}** (ArgumentError) the following keys must also be given when building struct User: [:name]
Keep in mind @enforce_keys is a simple compile-time guarantee
to aid developers when building structs. It is not enforced on
updates and it does not provide any sort of value-validation.
Types
It is recommended to define types for structs. By convention, such a type
is called t. To define a type for a struct, the struct literal syntax is
used:
It is recommended to only use the struct syntax when defining the struct's
type. When referring to another struct, it's better to use User.t() instead of
%User{}.
The types of the struct fields that are not included in %User{} default to
term() (see term/0).
Structs whose internal structure is private to the local module (pattern
matching them or directly accessing their fields should not be allowed) should
use the @opaque attribute. Structs whose internal structure is public should
use @type.
destructure(left, right)
(macro)
Destructures two lists, assigning each term in the
right one to the matching term in the left one.
Unlike pattern matching via =, if the sizes of the left
and right lists don't match, destructuring simply stops
instead of raising an error.
In the example above, even though the right list has more entries than the
left one, destructuring works fine. If the right list is smaller, the
remaining elements are simply set to nil:
Stops the execution of the calling process with the given reason.
Since evaluating this function causes the process to terminate,
it has no return value.
Inlined by the compiler.
Examples
When a process reaches its end, by default it exits with
reason :normal. You can also call exit/1 explicitly if you
want to terminate a process but not signal any failure:
exit(:normal)
In case something goes wrong, you can also use exit/1 with
a different reason:
exit(:seems_bad)
If the exit reason is not :normal, all the processes linked to the process
that exited will crash (unless they are trapping exits).
OTP exits
Exits are used by the OTP to determine if a process exited abnormally
or not. The following exits are considered "normal":
exit(:normal)
exit(:shutdown)
exit({:shutdown, term})
Exiting with any other reason is considered abnormal and treated
as a crash. This means the default supervisor behavior kicks in,
error reports are emitted, and so forth.
This behavior is relied on in many different places. For example,
ExUnit uses exit(:shutdown) when exiting the test process to
signal linked processes, supervision trees and so on to politely
shut down too.
CLI exits
Building on top of the exit signals mentioned above, if the
process started by the command line exits with any of the three
reasons above, its exit is considered normal and the Operating
System process will exit with status 0.
It is, however, possible to customize the operating system exit
signal by invoking:
exit({:shutdown,integer})
This will cause the operating system process to exit with the status given by
integer while signaling all linked Erlang processes to politely
shut down.
Any other exit reason will cause the operating system process to exit with
status 1 and linked Erlang processes to crash.
Returns true if module is loaded and contains a
public function with the given arity, otherwise false.
Unloaded modules
This function does not load the module in case it is not loaded
and Elixir lazily loads modules by default (except on releases).
This may lead to unexpected behaviour as the result of this function
may depend if another code has happened to load the given module
as argument beforehand. For example, this could manifest in mix test
by having tests that fail when running in isolation or depending on the
test seed. For those reasons, it is recommended to always check for
Code.ensure_loaded?/1 before function_exported?/3, unless you are
certain the module has been loaded before.
data is a nested structure (that is, a map, keyword
list, or struct that implements the Access behaviour).
The fun argument receives the value of key (or nil if key
is not present) and must return one of the following values:
a two-element tuple {current_value, new_value}. In this case,
current_value is the retrieved value which can possibly be operated on before
being returned. new_value is the new value to be stored under key.
:pop, which implies that the current value under key
should be removed from the structure and returned.
This function uses the Access module to traverse the structures
according to the given keys, unless the key is a function,
which is detailed in a later section.
Examples
This function is useful when there is a need to retrieve the current
value (or something calculated in function of the current value) and
update it at the same time. For example, it could be used to read the
current age of a user while increasing it by one in one pass:
Note the current value given to the anonymous function may be nil.
If any of the intermediate values are nil, it will raise:
iex> users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex> get_and_update_in(users,["jane",:age],&{&1,&1+1})** (ArgumentError) could not put/update key :age on a nil value
Functions as keys
If a key is a function, the function will be invoked passing three
arguments:
the operation (:get_and_update)
the data to be accessed
a function to be invoked next
This means get_and_update_in/3 can be extended to provide custom
lookups. The downside is that functions cannot be stored as keys
in the accessed data structures.
When one of the keys is a function, the function is invoked.
In the example below, we use a function to get and increment all
ages inside a list:
If the previous value before invoking the function is nil,
the function will receive nil as a value and must handle it
accordingly (be it by failing or providing a sane default).
The Access module ships with many convenience accessor functions,
like the all anonymous function defined above. See Access.all/0,
Access.key/2, and others as examples.
get_in(path)
(since 1.17.0)(macro)
Gets a key from the nested structure via the given path, with
nil-safe handling.
This is similar to get_in/2, except the path is extracted via
a macro rather than passing a list. For example:
get_in(opts[:foo][:bar])
Is equivalent to:
get_in(opts,[:foo,:bar])
Additionally, this macro can traverse structs:
get_in(struct.foo.bar)
In case any of the keys returns nil, then nil will be returned
and get_in/1 won't traverse any further.
Note that in order for this macro to work, the complete path must always
be visible by this macro. For more information about the supported path
expressions, please check get_and_update_in/2 docs.
get_in/2 can also use the accessors in the Access module
to traverse more complex data structures. For example, here we
use Access.all/0 to traverse a list:
If a key given to get_in/2 is a function, the function will be invoked
passing three arguments:
the operation (:get)
the data to be accessed
a function to be invoked next
This means get_in/2 can be extended to provide custom lookups.
That's precisely how the Access.all/0 key in the previous section
behaves. For example, we can manually implement such traversal as
follows:
The Access module ships with many convenience accessor functions.
See Access.all/0, Access.key/2, and others as examples.
Working with structs
By default, structs do not implement the Access behaviour required
by this function. Therefore, you can't do this:
get_in(some_struct,[:some_key,:nested_key])
There are two alternatives. Given structs have predefined keys,
we can use the struct.field notation:
some_struct.some_key.nested_key
However, the code above will fail if any of the values return nil.
If you also want to handle nil values, you can use get_in/1:
get_in(some_struct.some_key.nested_key)
Pattern-matching is another option for handling such cases,
which can be especially useful if you want to match on several
fields at once or provide custom return values:
This macro expects the first argument to be a condition and the second
argument to be a keyword list. Generally speaking, Elixir developers
prefer to use pattern matching and guards in function definitions and
case/2, as they are succinct and precise. However, not all conditions
can be expressed through patterns and guards, which makes if/2 a viable
alternative.
Similar to case/2, any assignment in the condition will be available
on both clauses, as well as after the if expression.
In the examples above, the do clause is evaluated and "yes" will be returned
because the condition evaluates to a truthy value (neither false nor nil).
Otherwise, the clause is not evaluated and nil will be returned:
iex> if3>5,do:"yes"niliex> ifnil,do:IO.puts("this won't be printed")nil
An else option can be given to specify the opposite:
iex> if3>5,do:"yes",else:"no""no"
Blocks examples
It's also possible to pass a block to the if/2 macro. The first
example above would be translated to:
iex> if7>5do...> "yes"...> end"yes"
Note that do-end become delimiters. The third example would
translate to:
Inspects the given argument according to the Inspect protocol.
The second argument is a keyword list with options to control
inspection.
Options
inspect/2 accepts a list of options that are internally
translated to an Inspect.Opts struct. Check the docs for
Inspect.Opts to see the supported options.
Note that the Inspect protocol does not necessarily return a valid
representation of an Elixir term. In such cases, the inspected result
must start with #. For example, inspecting a function will return:
inspect(fna,b->a+bend)#=> #Function<...>
The Inspect protocol can be derived to hide certain fields
from structs, so they don't show up in logs, inspects and similar.
See the "Deriving" section of the documentation of the Inspect
protocol for more information.
Variables assigned in the match will not be available outside of the
function call (unlike regular pattern matching with the = operator):
iex> match?(_x,1)trueiex> binding()[]
Values vs patterns
Remember the pin operator matches values, not patterns.
Passing a variable as the pattern will always return true and will
result in a warning that the variable is unused. Don't do this:
pattern=%{a::a}match?(pattern,%{b::b})#=> true
Similarly, moving an expression out the pattern may no longer preserve
its semantics. For example:
iex> match?([_|_],[1,2,3])truepattern=[_|_]match?(pattern,[1,2,3])** (CompileError) invalid use of _. _ can only be used inside patterns to ignore values and cannot be used in expressions. Make sure you are inside a pattern or change it accordingly
Another example is that a map as a pattern performs a subset match, but not
once assigned to a variable:
The pin operator will check if the values are equal, using ===/2, while
patterns have their own rules when matching maps, lists, and so forth.
Such behavior is not specific to match?/2. The following code also
throws an exception:
attrs=%{x:1}^attrs=%{x:1,y:2}#=> (MatchError) no match of right hand side value: %{x: 1, y: 2}
pop_in(path)
(macro)
Pops a key from the nested structure via the given path.
This is similar to pop_in/2, except the path is extracted via
a macro rather than passing a list. For example:
pop_in(opts[:foo][:bar])
Is equivalent to:
pop_in(opts,[:foo,:bar])
Note that in order for this macro to work, the complete path must always
be visible by this macro. For more information about the supported path
expressions, please check get_and_update_in/2 docs.
Uses the Access protocol to traverse the structures
according to the given keys, unless the key is a
function. If the key is a function, it will be invoked
as specified in get_and_update_in/3.
Puts a value in a nested structure via the given path.
This is similar to put_in/3, except the path is extracted via
a macro rather than passing a list. For example:
put_in(opts[:foo][:bar],:baz)
Is equivalent to:
put_in(opts,[:foo,:bar],:baz)
This also works with nested structs and the struct.path.to.value way to specify
paths:
put_in(struct.foo.bar,:baz)
Note that in order for this macro to work, the complete path must always
be visible by this macro. For more information about the supported path
expressions, please check get_and_update_in/2 docs.
Uses the Access module to traverse the structures
according to the given keys, unless the key is a
function. If the key is a function, it will be invoked
as specified in get_and_update_in/3.
If any of the intermediate values are nil, it will raise:
iex> users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex> put_in(users,["jane",:age],"oops")** (ArgumentError) could not put/update key :age on a nil value
raise(message)
(macro)
Raises an exception.
If message is a string, it raises a RuntimeError exception with it.
If message is an atom, it just calls raise/2 with the atom as the first
argument and [] as the second one.
If message is an exception struct, it is raised as is.
If message is anything else, raise will fail with an ArgumentError
exception.
Examples
iex> raise"oops"** (RuntimeError) oopstrydo1+:foorescuexin[ArithmeticError]->IO.puts("that was expected")raisexend
raise(exception, attributes)
(macro)
Raises an exception.
Calls the exception/1 function on the given argument (which has to be a
module name like ArgumentError or RuntimeError) passing attributes
in order to retrieve the exception struct.
@spec send(dest :: Process.dest(), message) :: message when message: any()
Sends a message to the given dest and returns the message.
dest may be a remote or local PID, a local port, a locally
registered name, or a tuple in the form of {registered_name, node} for a
registered name at another node.
By default, this sigil uses the built-in Calendar.ISO, which
requires dates to be written in the ISO8601 format:
~D[yyyy-mm-dd]
such as:
~D[2015-01-13]
If you are using alternative calendars, any representation can
be used as long as you follow the representation by a single space
and the calendar name:
~D[SOME-REPRESENTATION My.Alternative.Calendar]
The lower case ~d variant does not exist as interpolation
and escape characters are not useful for date sigils.
More information on dates can be found in the Date module.
Examples
iex> ~D[2015-01-13]~D[2015-01-13]
sigil_N(naive_datetime_string, modifiers)
(macro)
Handles the sigil ~N for naive date times.
By default, this sigil uses the built-in Calendar.ISO, which
requires naive date times to be written in the ISO8601 format:
If you are using alternative calendars, any representation can
be used as long as you follow the representation by a single space
and the calendar name:
~N[SOME-REPRESENTATION My.Alternative.Calendar]
The lower case ~n variant does not exist as interpolation
and escape characters are not useful for date time sigils.
More information on naive date times can be found in the
NaiveDateTime module.
While the ~r sigil allows parens and brackets to be used as delimiters,
it is preferred to use " or / to avoid escaping conflicts with reserved
regex characters.
sigil_S(term, modifiers)
(macro)
Handles the sigil ~S for strings.
It returns a string without interpolations and without escape
characters.
By default, this sigil uses the built-in Calendar.ISO, which
requires times to be written in the ISO8601 format:
~T[hh:mm:ss]~T[hh:mm:ss.ssssss]
such as:
~T[13:00:07]~T[13:00:07.123]
If you are using alternative calendars, any representation can
be used as long as you follow the representation by a single space
and the calendar name:
~T[SOME-REPRESENTATION My.Alternative.Calendar]
The lower case ~t variant does not exist as interpolation
and escape characters are not useful for time sigils.
More information on times can be found in the Time module.
If you are using alternative calendars, any representation can
be used as long as you follow the representation by a single space
and the calendar name:
~U[SOME-REPRESENTATION My.Alternative.Calendar]
The given datetime_string must include "Z" or "00:00" offset
which marks it as UTC, otherwise an error is raised.
The lower case ~u variant does not exist as interpolation
and escape characters are not useful for date time sigils.
More information on date times can be found in the DateTime module.
Typically developers do not use the spawn functions, instead they use
abstractions such as Task, GenServer and Agent, built on top of
spawn, that spawns processes with more conveniences in terms of
introspection and debugging.
Check the Process module for more process-related functions.
The anonymous function receives 0 arguments, and may return any value.
Spawns the given function fun from the given module passing it the given
args and returns its PID.
Typically developers do not use the spawn functions, instead they use
abstractions such as Task, GenServer and Agent, built on top of
spawn, that spawns processes with more conveniences in terms of
introspection and debugging.
Check the Process module for more process-related functions.
Spawns the given function, links it to the current process, and returns its PID.
Typically developers do not use the spawn functions, instead they use
abstractions such as Task, GenServer and Agent, built on top of
spawn, that spawns processes with more conveniences in terms of
introspection and debugging.
Check the Process module for more process-related functions. For more
information on linking, check Process.link/1.
The anonymous function receives 0 arguments, and may return any value.
Spawns the given function fun from the given module passing it the given
args, links it to the current process, and returns its PID.
Typically developers do not use the spawn functions, instead they use
abstractions such as Task, GenServer and Agent, built on top of
spawn, that spawns processes with more conveniences in terms of
introspection and debugging.
Check the Process module for more process-related functions. For more
information on linking, check Process.link/1.
Spawns the given function, monitors it and returns its PID
and monitoring reference.
Typically developers do not use the spawn functions, instead they use
abstractions such as Task, GenServer and Agent, built on top of
spawn, that spawns processes with more conveniences in terms of
introspection and debugging.
Check the Process module for more process-related functions.
The anonymous function receives 0 arguments, and may return any value.
Spawns the given module and function passing the given args,
monitors it and returns its PID and monitoring reference.
Typically developers do not use the spawn functions, instead they use
abstractions such as Task, GenServer and Agent, built on top of
spawn, that spawns processes with more conveniences in terms of
introspection and debugging.
Check the Process module for more process-related functions.
The struct argument may be an atom (which defines defstruct)
or a struct itself. The second argument is any Enumerable that
emits two-element tuples (key-value pairs) during enumeration.
Keys in the Enumerable that don't exist in the struct are automatically
discarded. Note that keys must be atoms, as only atoms are allowed when
defining a struct. If there are duplicate keys in the Enumerable, the last
entry will be taken (same behavior as Map.new/1).
This function is useful for dynamically creating and updating structs, as
well as for converting maps to structs; in the latter case, just inserting
the appropriate :__struct__ field into the map may not be enough and
struct/2 should be used instead.
The function struct!/2 emulates the compile time behavior
of structs. This means that:
when building a struct, as in struct!(SomeStruct, key: :value),
it is equivalent to %SomeStruct{key: :value} and therefore this
function will check if every given key-value belongs to the struct.
If the struct is enforcing any key via @enforce_keys, those will
be enforced as well;
when updating a struct, as in struct!(%SomeStruct{}, key: :value),
it is equivalent to %SomeStruct{struct | key: :value} and therefore this
function will check if every given key-value belongs to the struct.
tap(value, fun)
(since 1.12.0)(macro)
Pipes the first argument, value, into the second argument, a function fun,
and returns value itself.
Useful for running synchronous side effects in a pipeline, using the |>/2 operator.
Examples
iex> tap(1,fnx->x+1end)1
Most commonly, this is used in pipelines, using the |>/2 operator.
For example, let's suppose you want to inspect part of a data structure.
You could write:
Using throw/1 is generally discouraged, as it allows a function
to escape from its regular execution flow, which can make the code
harder to read. Furthermore, all thrown values must be caught by
try/catch. See try/1 for more information.
Inlined by the compiler.
to_charlist(term)
(macro)
Converts the given term to a charlist according to the List.Chars protocol.
Examples
iex> to_charlist(:foo)~c"foo"
to_string(term)
(macro)
Converts the argument to a string according to the
String.Chars protocol.
This is invoked when there is string interpolation.
Duration.t/0 structs can be converted to timeouts. The given duration must have
year and month fields set to 0, since those cannot be reliably converted to
milliseconds (due to the varying number of days in a month and year).
The duration argument can also be keyword list which can contain the following
keys, each appearing at most once with a non-negative integer value:
:week - the number of weeks (a week is always 7 days)
:day - the number of days (a day is always 24 hours)
:hour - the number of hours
:minute - the number of minutes
:second - the number of seconds
:millisecond - the number of milliseconds
The timeout is calculated as the sum of the components, each multiplied by
the corresponding factor.
Passing timeouts
You can also pass timeouts directly to this functions, that is, milliseconds or
the atom :infinity. In this case, this function just returns the given argument.
This macro evaluates and returns the do block passed in as the second
argument if condition evaluates to a falsy value (false or nil).
Otherwise, it returns the value of the else block if present or nil if not.
iex> unless(Enum.empty?([]),do:"Hello")niliex> unless(Enum.empty?([1,2,3]),do:"Hello")"Hello"iex> unlessEnum.sum([2,2])==5do...> "Math still works"...> else...> "Math is broken"...> end"Math still works"
update_in(path, fun)
(macro)
Updates a nested structure via the given path.
This is similar to update_in/3, except the path is extracted via
a macro rather than passing a list. For example:
update_in(opts[:foo][:bar],&(&1+1))
Is equivalent to:
update_in(opts,[:foo,:bar],&(&1+1))
This also works with nested structs and the struct.path.to.value way to specify
paths:
update_in(struct.foo.bar,&(&1+1))
Note that in order for this macro to work, the complete path must always
be visible by this macro. For more information about the supported path
expressions, please check get_and_update_in/2 docs.
Uses the Access module to traverse the structures
according to the given keys, unless the key is a
function. If the key is a function, it will be invoked
as specified in get_and_update_in/3.
data is a nested structure (that is, a map, keyword
list, or struct that implements the Access behaviour).
The fun argument receives the value of key (or nil
if key is not present) and the result replaces the value
in the structure.
Note the current value given to the anonymous function may be nil.
If any of the intermediate values are nil, it will raise:
iex> users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex> update_in(users,["jane",:age],&&1+1)** (ArgumentError) could not put/update key :age on a nil value
use(module, opts \\ [])
(macro)
Uses the given module in the current context.
When calling:
useMyModule,some::options
Elixir will invoke MyModule.__using__/1 passing the second argument of
use as its argument. Since __using__/1 is typically a macro, all
the usual macro rules apply, and its return value should be quoted code
that is then inserted where use/2 is called.
Code injection
use MyModule works as a code-injection point in the caller.
Given the caller of use MyModule has little control over how the
code is injected, use/2 should be used with care. If you can,
avoid use in favor of import/2 or alias/2 whenever possible.
Examples
For example, to write test cases using the ExUnit framework provided
with Elixir, a developer should use the ExUnit.Case module:
defmoduleExUnit.Casedodefmacro__using__(opts)do# do something with optsquotedo# return some code to inject in the callerendendend
Best practices
__using__/1 is typically used when there is a need to set some state
(via module attributes) or callbacks (like @before_compile, see the
documentation for Module for more information) into the caller.
__using__/1 may also be used to alias, require, or import functionality
from different modules:
In such cases, developers should instead import or alias the module
directly, so that they can customize those as they wish,
without the indirection behind use/2. Developers must also avoid
defining functions inside __using__/1.
Given use MyModule can generate any code, it may not be easy for
developers to understand the impact of use MyModule.
For this reason, to provide guidance and clarity, we recommend developers
to include an admonition block in their @moduledoc that explains how
use MyModule impacts their code. As an example, the GenServer documentation
outlines:
use GenServer
When you use GenServer, the GenServer module will
set @behaviour GenServer and define a child_spec/1
function, so your module can be used as a child
in a supervision tree.
This provides a quick summary of how using a module impacts the user code.
Keep in mind to only list changes made to the public API of the module.
For example, if use MyModule sets an internal attribute called
@_my_module_info and this attribute is never meant to be public,
it must not be listed.
For convenience, the markup notation to generate the admonition block
above is:
Marks that the given variable should not be hygienized.
This macro expects a variable and it is typically invoked
inside quote/2 to mark that a variable
should not be hygienized. See quote/2 for more information.
In the example above, the list [1, [2], 3] is passed as the first argument
to the List.flatten/1 function, then the flattened list is passed as the
first argument to the Enum.map/2 function which doubles each element of the
list.
In other words, the expression above simply translates to:
Enum.map(List.flatten([1,[2],3]),fnx->x*2end)
Pitfalls
There are two common pitfalls when using the pipe operator.
The first one is related to operator precedence. For example,
the following expression:
String.graphemes"Hello"|>Enum.reverse
Translates to:
String.graphemes("Hello"|>Enum.reverse())
which results in an error as the Enumerable protocol is not defined
for binaries. Adding explicit parentheses resolves the ambiguity:
String.graphemes("Hello")|>Enum.reverse()
Or, even better:
"Hello"|>String.graphemes()|>Enum.reverse()
The second limitation is that Elixir always pipes to a function
call. Therefore, to pipe into an anonymous function, you need to
invoke it:
then/2 is most commonly used when you want to pipe to a function
but the value is expected outside of the first argument, such as
above. By replacing some_fun by its value, we get:
Provides a short-circuit operator that evaluates and returns the second
expression only if the first one does not evaluate to a truthy value (that is,
it is either nil or false). Returns the first expression otherwise.
Note that, unlike or/2, this operator accepts any expression
as the first argument, not only booleans.
You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.