Kernel(Elixir v1.18.3)
View SourceKernel
is Elixir's default environment.
It mainly consists of:
- 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 invokeKernel
functions and macros anywhere in Elixir codewithout the use of theKernel.
prefix since they have all beenautomatically imported. For example, in IEx, you can call:
iex>is_number(13)true
If you don't want to import a function or macro fromKernel
, use the:except
option and then list the function/macro by arity:
importKernel,except:[if:2,unless:2]
Seeimport/2
for more information on importing.
Elixir also has special forms that are always imported andcannot be skipped. These are described inKernel.SpecialForms
.
The standard library
Kernel
provides the basic capabilities the Elixir standard libraryis built on top of. It is recommended to explore the standard libraryfor advanced functionality. Here are the main groups of modules in thestandard library (this list is not a complete reference, see thedocumentation sidebar for all entries).
Built-in types
The following modules handle Elixir built-in data types:
Atom
- literal constants with a name (true
,false
, andnil
are atoms)Float
- numbers with floating point precisionFunction
- a reference to code chunk, created with thefn/1
special formInteger
- whole numbers (not fractions)List
- collections of a variable number of elements (linked lists)Map
- collections of key-value pairsProcess
- light-weight threads of executionPort
- mechanisms to interact with the external worldTuple
- collections of a fixed number of elements
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 canbe 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 typeslisted above. Some of them are:
Date
-year-month-day
structs in a given calendarDateTime
- date and time with time zone in a given calendarException
- data raised from errors and unexpected scenariosMapSet
- unordered collections of unique elementsNaiveDateTime
- date and time without time zone in a given calendarKeyword
- lists of two-element tuples, often representing optional valuesRange
- inclusive ranges between two integersRegex
- regular expressionsString
- UTF-8 encoded binaries representing charactersTime
-hour:minute:second
structs in a given calendarURI
- representation of URIs that identify resourcesVersion
- representation of versions and requirements
System modules
Modules that interface with the underlying system, such as:
IO
- handles input and outputFile
- interacts with the underlying file systemPath
- manipulates file system pathsSystem
- reads and writes system information
Protocols
Protocols add polymorphic dispatch to Elixir. They are contractsimplementable by data types. SeeProtocol
for more information onprotocols. Elixir provides the following protocols in the standard library:
Collectable
- collects data into a data typeEnumerable
- handles collections in Elixir. TheEnum
moduleprovides eager functions for working with collections, theStream
module provides lazy functionsInspect
- converts data types into their programming languagerepresentationList.Chars
- converts data types to their outside worldrepresentation as charlists (non-programming based)String.Chars
- converts data types to their outside worldrepresentation 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.
Agent
- a process that encapsulates mutable stateApplication
- functions for starting, stopping and configuringapplicationsGenServer
- a generic client-server APIRegistry
- a key-value process-based storageSupervisor
- a process that is responsible for starting,supervising and shutting down other processesTask
- a process that performs computationsTask.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 behaviorsin more detail. Those are:
- Compatibility and deprecations - listscompatibility 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
- Naming conventions - naming conventions for Elixir code
- Operators reference - lists all Elixir operators and their precedences
- Patterns and guards - an introduction to patterns,guards, and extensions
- Syntax reference - the language syntax reference
- Typespecs reference- types and function specifications, including list of types
- Unicode syntax - outlines Elixir support for Unicode
Guards
This module includes the built-in guards used by Elixir developers.They are a predefined set of functions and macros that augment patternmatching, typically invoked after thewhen
operator. For example:
defdrive(%User{age:age})whenage>=16do...end
The clause above will only be invoked if the user's age is more thanor equal to 16. Guards also support joining multiple conditions withand
andor
. The whole guard is true if all guard expressions willevaluate totrue
. A more complete introduction to guards is availablein thePatterns and guards page.
Truthy and falsy values
Besides the booleanstrue
andfalse
, Elixir has theconcept of a "truthy" or "falsy" value.
- a value is truthy when it is neither
false
nornil
- a value is falsy when it is either
false
ornil
Elixir has functions, likeand/2
, thatonly work withbooleans, but also functions that work with thesetruthy/falsy values, like&&/2
and!/1
.
Structural comparison
The functions in this module perform structural comparison. This allowsdifferent data types to be compared using comparison operators:
1<:an_atom
This is possible so Elixir developers can create collections, such asdictionaries and ordered sets, that store a mixture of data types in them.To understand why this matters, let's discuss the two types of comparisonswe find in software:structural andsemantic.
Structural means we are comparing the underlying data structures and we oftenwant those operations to be as fast as possible, because it is used to powerseveral algorithms and data structures in the language. A semantic comparisonworries about what each data type represents. For example, semanticallyspeaking, it doesn't make sense to compareTime
withDate
.
One example that shows the differences between structural and semanticcomparisons are strings: "alien" sorts less than "office" ("alien" < "office"
)but "álien" is greater than "office". This happens because<
compares theunderlying bytes that form the string. If you were doing alphabetical listing,you may want "álien" to also appear before "office".
This meanscomparisons in Elixir are structural, as it has the goalof comparing data types as efficiently as possible to create flexibleand performant data structures. This distinction is specially importantfor functions that provide ordering, such as>/2
,</2
,>=/2
,<=/2
,min/2
, andmax/2
. For example:
~D[2017-03-31]>~D[2017-04-01]
will returntrue
because structural comparison compares the:day
field before:month
or:year
. Luckily, the Elixir compiler willdetect whenever comparing structs or whenever comparing code that iseither always true or false, and emit a warning accordingly.
In order to perform semantic comparisons, the relevant data-typesprovide acompare/2
function, such asDate.compare/2
:
iex>Date.compare(~D[2017-03-31],~D[2017-04-01]):lt
Alternatively, you can use the functions in theEnum
module tosort or compute a maximum/minimum:
iex>Enum.sort([~D[2017-03-31],~D[2017-04-01]],Date)[~D[2017-03-31],~D[2017-04-01]]iex>Enum.max([~D[2017-03-31],~D[2017-04-01]],Date)~D[2017-04-01]
The second argument is precisely the module to be used for semanticcomparison. Keeping this distinction is important, because if semanticcomparison was used by default for implementing data structures andalgorithms, 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 referencepurposes, it is not required by Elixir developers to know it by heart.
Term ordering
number<atom<reference<function<port<pid<tuple<map<list<bitstring
When comparing two numbers of different types (a number being eitheran integer or a float), a conversion to the type with greater precisionwill always occur, unless the comparison operator used is either===/2
or!==/2
. A float will be considered more precise than an integer, unlessthe float is greater/less than +/-9007199254740992.0 respectively,at which point all the significant figures of the float are to the leftof the decimal point. This behavior exists so that the comparison of largenumbers 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.
Truthy values:
iex>!!truetrueiex>!!5trueiex>!![1,2]trueiex>!!"foo"true
Falsy values (of which there are exactly two):
iex>!!falsefalseiex>!!nilfalse
Inlining
Some of the functions described in this module are inlined bythe 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 someof them are allowed in guards and others are used for compileroptimizations.
Most of the inlined functions can be seen in effect whencapturing 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".
Summary
Guards
Arithmetic multiplication operator.
Arithmetic positive unary operator.
Arithmetic addition operator.
Arithmetic negative unary operator.
Arithmetic subtraction operator.
Arithmetic division operator.
Not equal to operator.
Strictly not equal to operator.
Less-than operator.
Less-than or equal to operator.
Equal to operator. Returnstrue
if the two terms are equal.
Strictly equal to operator.
Greater-than operator.
Greater-than or equal to operator.
Returns an integer or float which is the arithmetical absolute value ofnumber
.
Strictly boolean "and" operator.
Extracts the part of the binary atstart
withsize
.
Returns an integer which is the size in bits ofbitstring
.
Returns the number of bytes needed to containbitstring
.
Returns the smallest integer greater than or equal tonumber
.
Performs an integer division.
Gets the element at the zero-basedindex
intuple
.
Returns the largest integer smaller than or equal tonumber
.
Returns the head of a list. RaisesArgumentError
if the list is empty.
Membership operator.
Returnstrue
ifterm
is an atom, otherwise returnsfalse
.
Returnstrue
ifterm
is a binary, otherwise returnsfalse
.
Returnstrue
ifterm
is a bitstring (including a binary), otherwise returnsfalse
.
Returnstrue
ifterm
is either the atomtrue
or the atomfalse
(i.e.,a boolean), otherwise returnsfalse
.
Returnstrue
ifterm
is an exception, otherwise returnsfalse
.
Returnstrue
ifterm
is an exception ofname
, otherwise returnsfalse
.
Returnstrue
ifterm
is a floating-point number, otherwise returnsfalse
.
Returnstrue
ifterm
is a function, otherwise returnsfalse
.
Returnstrue
ifterm
is a function that can be applied witharity
number of arguments;otherwise returnsfalse
.
Returnstrue
ifterm
is an integer, otherwise returnsfalse
.
Returnstrue
ifterm
is a list with zero or more elements, otherwise returnsfalse
.
Returnstrue
ifterm
is a map, otherwise returnsfalse
.
Returnstrue
ifkey
is a key inmap
, otherwise returnsfalse
.
Returnstrue
ifterm
isnil
,false
otherwise.
Returnstrue
ifterm
is a map that is not a struct, otherwisereturnsfalse
.
Returnstrue
ifterm
is either an integer or a floating-point number;otherwise returnsfalse
.
Returnstrue
ifterm
is a PID (process identifier), otherwise returnsfalse
.
Returnstrue
ifterm
is a port identifier, otherwise returnsfalse
.
Returnstrue
ifterm
is a reference, otherwise returnsfalse
.
Returnstrue
ifterm
is a struct, otherwise returnsfalse
.
Returnstrue
ifterm
is a struct ofname
, otherwise returnsfalse
.
Returnstrue
ifterm
is a tuple, otherwise returnsfalse
.
Returns the length oflist
.
Returns the size of a map.
Returns an atom representing the name of the local node.If the node is not alive,:nonode@nohost
is returned instead.
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.
Strictly boolean "not" operator.
Strictly boolean "or" operator.
Computes the remainder of an integer division.
Rounds a number to the nearest integer.
Returns the PID (process identifier) of the calling process.
Returns the tail of a list. RaisesArgumentError
if the list is empty.
Returns the integer part ofnumber
.
Returns the size of a tuple.
Functions
Boolean "and" operator.
Power operator.
List concatenation operator. Concatenates a proper list and a term, returning a list.
List subtraction operator. Removes the first occurrence of an elementon the left list for each element on the right.
Creates the full-slice range0..-1//1
.
Creates a range fromfirst
tolast
.
Creates a range fromfirst
tolast
withstep
.
Boolean "not" operator.
Binary concatenation operator. Concatenates two binaries.
Text-based match operator. Matches the term on theleft
against the regular expression or string on theright
.
Module attribute unary operator.
When used inside quoting, marks that the given alias should notbe hygienized. This means the alias will be expanded whenthe macro is expanded.
Invokes the given anonymous functionfun
with the list ofargumentsargs
.
Invokes the given function frommodule
with the list ofargumentsargs
.
Returns a binary from the offset given by the start of therange to the offset given by the end of the range.
Returns a binary starting at the offsetstart
and of the givensize
.
Returns the binding for the given context as a keyword list.
Debugs the givencode
.
Defines a public function with the given name and body.
Defines a function that delegates to another module.
Defines an exception.
Defines a macro suitable for use in guard expressions.
Defines a private macro suitable for use in guard expressions.
Defines an implementation for the given protocol.
Defines a public macro with the given name and body.
Defines a private macro with the given name and body.
Defines a module given by name with the given contents.
Makes the given definitions in the current module overridable.
Defines a private function with the given name and body.
Defines a protocol.
Defines a struct.
Destructures two lists, assigning each term in theright one to the matching term in the left one.
Stops the execution of the calling process with the given reason.
Returnstrue
ifmodule
is loaded and contains apublicfunction
with the givenarity
, otherwisefalse
.
Gets a value and updates a nested data structure via the givenpath
.
Gets a value and updates a nested structure.
Gets a key from the nested structure via the givenpath
, withnil-safe handling.
Gets a value from a nested structure with nil-safe handling.
Provides anif/2
macro.
Inspects the given argument according to theInspect
protocol.The second argument is a keyword list with options to controlinspection.
Returnstrue
ifmodule
is loaded and contains apublicmacro
with the givenarity
, otherwisefalse
.
Returns an almost unique reference.
A convenience macro that checks if the right side (an expression) matches theleft side (a pattern).
Returns the biggest of the two given terms according totheir structural comparison.
Returns the smallest of the two given terms according totheir structural comparison.
Pops a key from the nested structure via the givenpath
.
Pops a key from the given nested structure.
Putsvalue
at the given zero-basedindex
intuple
.
Puts a value in a nested structure via the givenpath
.
Puts a value in a nested structure.
Raises an exception.
Raises an exception.
Raises an exception preserving a previous stacktrace.
Raises an exception preserving a previous stacktrace.
Sends a message to the givendest
and returns the message.
Handles the sigil~C
for charlists.
Handles the sigil~c
for charlists.
Handles the sigil~D
for dates.
Handles the sigil~N
for naive date times.
Handles the sigil~r
for regular expressions.
Handles the sigil~S
for strings.
Handles the sigil~s
for strings.
Handles the sigil~T
for times.
Handles the sigil~U
to create a UTCDateTime
.
Handles the sigil~W
for list of words.
Handles the sigil~w
for list of words.
Spawns the given function and returns its PID.
Spawns the given functionfun
from the givenmodule
passing it the givenargs
and returns its PID.
Spawns the given function, links it to the current process, and returns its PID.
Spawns the given functionfun
from the givenmodule
passing it the givenargs
, links it to the current process, and returns its PID.
Spawns the given function, monitors it and returns its PIDand monitoring reference.
Spawns the given module and function passing the given args,monitors it and returns its PID and monitoring reference.
Creates and updates a struct.
Similar tostruct/2
but checks for key validity.
Pipes the first argument,value
, into the second argument, a functionfun
,and returnsvalue
itself.
Pipes the first argument,value
, into the second argument, a functionfun
,and returns the result of callingfun
.
A non-local return from a function.
Converts the given term to a charlist according to theList.Chars
protocol.
Converts the argument to a string according to theString.Chars
protocol.
Constructs a millisecond timeout from the given components, duration, or timeout.
Provides anunless
macro.
Updates a nested structure via the givenpath
.
Updates a key in a nested structure.
Uses the given module in the current context.
Marks that the given variable should not be hygienized.
Pipe operator.
Boolean "or" operator.
Guards
@specinteger() *integer() ::integer()
@specfloat() *float() ::float()
@specinteger() *float() ::float()
@specfloat() *integer() ::float()
Arithmetic multiplication operator.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1*22
Arithmetic positive unary operator.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>+11
@specinteger() +integer() ::integer()
@specfloat() +float() ::float()
@specinteger() +float() ::float()
@specfloat() +integer() ::float()
Arithmetic addition operator.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1+23
@spec -0 :: 0
@spec -pos_integer() ::neg_integer()
@spec -neg_integer() ::pos_integer()
@spec -float() ::float()
Arithmetic negative unary operator.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>-2-2
@specinteger() -integer() ::integer()
@specfloat() -float() ::float()
@specinteger() -float() ::float()
@specfloat() -integer() ::float()
Arithmetic subtraction operator.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1-2-1
Arithmetic division operator.
The result is always a float. Usediv/2
andrem/2
if you wantan integer division or the remainder.
RaisesArithmeticError
ifright
is 0 or 0.0.
Allowed in guard tests. Inlined by the compiler.
Examples
1/2#=> 0.5-3.0/2.0#=> -1.55/1#=> 5.07/0** (ArithmeticError) bad argument in arithmetic expression
Not equal to operator.
Returnstrue
if the two terms are not equal.
This operator considers 1 and 1.0 to be equal. For matchcomparison, use!==/2
instead.
This performs a structural comparison where all Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1!=2trueiex>1!=1.0false
Strictly not equal to operator.
Returnstrue
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 Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1!==2trueiex>1!==1.0true
Less-than operator.
Returnstrue
ifleft
is less thanright
.
This performs a structural comparison where all Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1<2true
Less-than or equal to operator.
Returnstrue
ifleft
is less than or equal toright
.
This performs a structural comparison where all Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1<=2true
Equal to operator. Returnstrue
if the two terms are equal.
This operator considers 1 and 1.0 to be equal. For strictersemantics, use===/2
instead.
This performs a structural comparison where all Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1==2falseiex>1==1.0true
Strictly equal to operator.
Returnstrue
if the two terms are exactly equal.
The terms are only considered to be exactly equal if theyhave the same value and are of the same type. For example,1 == 1.0
returnstrue
, but since they are of differenttypes,1 === 1.0
returnsfalse
.
This performs a structural comparison where all Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1===2falseiex>1===1.0false
Greater-than operator.
Returnstrue
ifleft
is more thanright
.
This performs a structural comparison where all Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1>2false
Greater-than or equal to operator.
Returnstrue
ifleft
is more than or equal toright
.
This performs a structural comparison where all Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>1>=2false
Returns an integer or float which is the arithmetical absolute value ofnumber
.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>abs(-3.33)3.33iex>abs(-3)3
Strictly boolean "and" operator.
Ifleft
isfalse
, returnsfalse
, otherwise returnsright
.
Requires only theleft
operand to be a boolean since it short-circuits. Iftheleft
operand is not a boolean, aBadBooleanError
exception is raised.
Allowed in guard tests.
Examples
iex>trueandfalsefalseiex>trueand"yay!""yay!"iex>"yay!"andtrue** (BadBooleanError) expected a boolean on left-side of "and", got: "yay!"
@spec binary_part(binary(),non_neg_integer(),integer()) ::binary()
Extracts the part of the binary atstart
withsize
.
Ifstart
orsize
reference in any way outside the binary,anArgumentError
exception is raised.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>binary_part("foo",1,2)"oo"
A negativesize
can be used to extract bytes that comebefore the byteatstart
:
iex>binary_part("Hello",5,-3)"llo"
AnArgumentError
is raised when thesize
is outside of the binary:
binary_part("Hello",0,10)** (ArgumentError) argument error
@spec bit_size(bitstring()) ::non_neg_integer()
Returns an integer which is the size in bits ofbitstring
.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>bit_size(<<433::16,3::3>>)19iex>bit_size(<<1,2,3>>)24
@spec byte_size(bitstring()) ::non_neg_integer()
Returns the number of bytes needed to containbitstring
.
That is, if the number of bits inbitstring
is not divisible by 8, theresulting number of bytes will be rounded up (by excess). This operationhappens in constant time.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>byte_size(<<433::16,3::3>>)3iex>byte_size(<<1,2,3>>)3
Returns the smallest integer greater than or equal tonumber
.
If you want to perform ceil operation on other decimal places,useFloat.ceil/2
instead.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>ceil(10)10iex>ceil(10.1)11iex>ceil(-10.1)-10
@spec div(integer(),neg_integer() |pos_integer()) ::integer()
Performs an integer division.
Raises anArithmeticError
exception if one of the arguments is not aninteger, or when thedivisor
is0
.
div/2
performstruncated integer division. This means thatthe result is always rounded towards zero.
If you want to perform floored integer division (rounding towards negative infinity),useInteger.floor_div/2
instead.
Allowed in guard tests. Inlined by the compiler.
Examples
div(5,2)#=> 2div(6,-4)#=> -1div(-99,2)#=> -49div(100,0)** (ArithmeticError) bad argument in arithmetic expression
@spec elem(tuple(),non_neg_integer()) ::term()
Gets the element at the zero-basedindex
intuple
.
It raisesArgumentError
when index is negative or it is out of range of the tuple elements.
Allowed in guard tests. Inlined by the compiler.
Examples
tuple={:foo,:bar,3}elem(tuple,1)#=> :barelem({},0)** (ArgumentError) argument errorelem({:foo,:bar},2)** (ArgumentError) argument error
Returns the largest integer smaller than or equal tonumber
.
If you want to perform floor operation on other decimal places,useFloat.floor/2
instead.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>floor(10)10iex>floor(9.7)9iex>floor(-9.7)-10
@spec hd(nonempty_maybe_improper_list(elem,term())) :: elem when elem:term()
Returns the head of a list. RaisesArgumentError
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
hd([1,2,3,4])#=> 1hd([1|2])#=> 1
Giving it an empty list raises:
hd([])** (ArgumentError) argument error
Membership operator.
Checks if the element on the left-hand side is a member of thecollection 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 toEnum.member?/2
. The example above would translate to:
Enum.member?([1,2,3],x)
Elixir also supportsleft not in right
, which evaluates tonot(left in right)
:
iex>x=1iex>xnotin[1,2,3]false
Guards
Thein/2
operator (as well asnot in
) can be used in guard clauses aslong 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 validguard 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, itis best to stop using guards and use a more appropriate data structure, suchasMapSet
.
If the right-hand side is a range, a more efficient comparison check will bedone. For example:
whenxin1..1000
translates roughly to:
whenx>=1andx<=1000
AST considerations
left not in right
is parsed by the compiler into the AST:
{:not,_,[{:in,_,[left,right]}]}
This is the same AST asnot(left in right)
.
Additionally,Macro.to_string/2
andCode.format_string!/2
will translate all occurrences of this AST toleft not in right
.
Returnstrue
ifterm
is an atom, otherwise returnsfalse
.
Notetrue
,false
, andnil
are atoms in Elixir, as well asmodule names. Therefore this function will returntrue
to allof those values.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>is_atom(:name)trueiex>is_atom(false)trueiex>is_atom(AnAtom)trueiex>is_atom("string")false
Returnstrue
ifterm
is a binary, otherwise returnsfalse
.
A binary always contains a complete number of bytes.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>is_binary("foo")trueiex>is_binary(<<1::3>>)false
Returnstrue
ifterm
is a bitstring (including a binary), otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>is_bitstring("foo")trueiex>is_bitstring(<<1::3>>)true
Returnstrue
ifterm
is either the atomtrue
or the atomfalse
(i.e.,a boolean), otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>is_boolean(false)trueiex>is_boolean(true)trueiex>is_boolean(:test)false
Returnstrue
ifterm
is an exception, otherwise returnsfalse
.
Allowed in guard tests.
Examples
iex>is_exception(%RuntimeError{})trueiex>is_exception(%{})false
Returnstrue
ifterm
is an exception ofname
, otherwise returnsfalse
.
Allowed in guard tests.
Examples
iex>is_exception(%RuntimeError{},RuntimeError)trueiex>is_exception(%RuntimeError{},Macro.Env)false
Returnstrue
ifterm
is a floating-point number, otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Returnstrue
ifterm
is a function, otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>is_function(fnx->x+xend)trueiex>is_function("not a function")false
@spec is_function(term(),non_neg_integer()) ::boolean()
Returnstrue
ifterm
is a function that can be applied witharity
number of arguments;otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>is_function(fnx->x*2end,1)trueiex>is_function(fnx->x*2end,2)false
Returnstrue
ifterm
is an integer, otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Returnstrue
ifterm
is a list with zero or more elements, otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Returnstrue
ifterm
is a map, otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Structs are maps
Structs are also maps, and many of Elixir data structures are implementedusing structs:Range
s,Regex
es,Date
s...
iex>is_map(1..10)trueiex>is_map(~D[2024-04-18])true
If you mean to specifically check for non-struct maps, useis_non_struct_map/1
instead.
iex>is_non_struct_map(1..10)false
Returnstrue
ifkey
is a key inmap
, otherwise returnsfalse
.
It raisesBadMapError
if the first element is not a map.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>is_map_key(%{a:"foo",b:"bar"},:a)trueiex>is_map_key(%{a:"foo",b:"bar"},:c)false
Returnstrue
ifterm
isnil
,false
otherwise.
Allowed in guard clauses.
Examples
iex>is_nil(1+2)falseiex>is_nil(nil)true
Returnstrue
ifterm
is a map that is not a struct, otherwisereturnsfalse
.
Allowed in guard tests.
Examples
iex>is_non_struct_map(%{})trueiex>is_non_struct_map(URI.parse("/"))falseiex>is_non_struct_map(nil)false
Returnstrue
ifterm
is either an integer or a floating-point number;otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Returnstrue
ifterm
is a PID (process identifier), otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Returnstrue
ifterm
is a port identifier, otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Returnstrue
ifterm
is a reference, otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
Returnstrue
ifterm
is a struct, otherwise returnsfalse
.
Allowed in guard tests.
Examples
iex>is_struct(URI.parse("/"))trueiex>is_struct(%{})false
Returnstrue
ifterm
is a struct ofname
, otherwise returnsfalse
.
is_struct/2
does not check thatname
exists and is a valid struct.If you want such validations, you must pattern match on the structinstead, such asmatch?(%URI{}, arg)
.
Allowed in guard tests.
Examples
iex>is_struct(URI.parse("/"),URI)trueiex>is_struct(URI.parse("/"),Macro.Env)false
Returnstrue
ifterm
is a tuple, otherwise returnsfalse
.
Allowed in guard tests. Inlined by the compiler.
@spec length(list()) ::non_neg_integer()
Returns the length oflist
.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>length([1,2,3,4,5,6,7,8,9])9
@spec map_size(map()) ::non_neg_integer()
Returns the size of a map.
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
@spec node() ::node()
Returns an atom representing the name of the local node.If the node is not alive,:nonode@nohost
is returned instead.
Allowed in guard tests. 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.
Allowed in guard tests. Inlined by the compiler.
@spec not true :: false
@spec not false :: true
Strictly boolean "not" operator.
value
must be a boolean; if it's not, anArgumentError
exception is raised.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>notfalsetrue
Strictly boolean "or" operator.
Ifleft
istrue
, returnstrue
, otherwise returnsright
.
Requires only theleft
operand to be a boolean since it short-circuits.If theleft
operand is not a boolean, aBadBooleanError
exception israised.
Allowed in guard tests.
Examples
iex>trueorfalsetrueiex>falseor4242iex>42orfalse** (BadBooleanError) expected a boolean on left-side of "or", got: 42
@spec rem(integer(),neg_integer() |pos_integer()) ::integer()
Computes the remainder of an integer division.
rem/2
uses truncated division, which means thatthe result will always have the sign of thedividend
.
Raises anArithmeticError
exception if one of the arguments is not aninteger, or when thedivisor
is0
.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>rem(5,2)1iex>rem(6,-4)2
Rounds a number to the nearest integer.
If the number is equidistant to the two nearest integers, rounds away from zero.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>round(5.6)6iex>round(5.2)5iex>round(-9.9)-10iex>round(-9)-9iex>round(2.5)3iex>round(-2.5)-3
@spec self() ::pid()
Returns the PID (process identifier) of the calling process.
Allowed in guard clauses. Inlined by the compiler.
@spec tl(nonempty_maybe_improper_list(elem, last)) ::maybe_improper_list(elem, last) | lastwhen elem:term(), last:term()
Returns the tail of a list. RaisesArgumentError
if the list is empty.
The tail of a list is the list without its first element.
It works with improper lists.
Allowed in guard tests. Inlined by the compiler.
Examples
tl([1,2,3,:go])#=> [2, 3, :go]tl([:one])#=> []tl([:a,:b|:improper_end])#=> [:b | :improper_end]tl([:a|%{b:1}])#=> %{b: 1}
Giving it an empty list raises:
tl([])** (ArgumentError) argument error
Returns the integer part ofnumber
.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>trunc(5.4)5iex>trunc(-5.99)-5iex>trunc(-5)-5
@spec tuple_size(tuple()) ::non_neg_integer()
Returns the size of a tuple.
This operation happens in constant time.
Allowed in guard tests. Inlined by the compiler.
Examples
iex>tuple_size({:a,:b,:c})3
Functions
Boolean "and" operator.
Provides a short-circuit operator that evaluates and returnsthe second expression only if the first one evaluates to a truthy value(neitherfalse
nornil
). Returns the first expressionotherwise.
Not allowed in guard clauses.
Examples
iex>Enum.empty?([])&&Enum.empty?([])trueiex>List.first([])&&trueniliex>Enum.empty?([])&&List.first([1])1iex>false&&throw(:bad)false
Note that, unlikeand/2
, this operator accepts any expressionas the first argument, not only booleans.
@specinteger() **non_neg_integer() ::integer()
@specinteger() **neg_integer() ::float()
@specfloat() **float() ::float()
@specinteger() **float() ::float()
@specfloat() **integer() ::float()
Power operator.
It takes two numbers for input. If both are integers and the right-handside (theexponent
) is also greater than or equal to 0, then the resultwill also be an integer. Otherwise it returns a float.
Examples
iex>2**24iex>2**-40.0625iex>2.0**24.0iex>2**2.04.0
@spec [] ++ a :: a when a:term()
@spec [...] ++term() ::maybe_improper_list()
List concatenation operator. Concatenates a proper list and a term, returning a list.
The complexity ofa ++ b
is proportional tolength(a)
, so avoid repeatedlyappending to lists of arbitrary length, for example,list ++ [element]
.Instead, consider prepending via[element | rest]
and then reversing.
If theright
operand is not a proper list, it returns an improper list.If theleft
operand is not a proper list, it raisesArgumentError
.If theleft
operand is an empty list, it returns theright
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
The++/2
operator is right associative, meaning:
iex>[1,2,3]--[1]++[2][3]
As it is equivalent to:
iex>[1,2,3]--([1]++[2])[3]
List subtraction operator. Removes the first occurrence of an elementon the left list for each element on the right.
This function is optimized so the complexity ofa -- b
is proportionaltolength(a) * log(length(b))
. See also theErlang efficiencyguide.
Inlined by the compiler.
Examples
iex>[1,2,3]--[1,2][3]iex>[1,2,3,2,1]--[1,2,2][3,1]
The--/2
operator is right associative, meaning:
iex>[1,2,3]--[2]--[3][1,3]
As it is equivalent to:
iex>[1,2,3]--([2]--[3])[1,3]
Creates the full-slice range0..-1//1
.
This macro returns a range with the following properties:
When enumerated, it is empty
When used as a
slice
, it returns the sliced element as is
See..///3
and theRange
module for more information.
Examples
iex>Enum.to_list(..)[]iex>String.slice("Hello world!",..)"Hello world!"
Creates a range fromfirst
tolast
.
If first is less than last, the range will be increasing fromfirst to last. If first is equal to last, the range will containone element, which is the number itself.
If first is more than last, the range will be decreasing from firstto last, albeit this behavior is deprecated. Instead prefer toexplicitly list the step withfirst..last//-1
.
See theRange
module for more information.
Examples
iex>0in1..3falseiex>2in1..3trueiex>Enum.to_list(1..3)[1,2,3]
Creates a range fromfirst
tolast
withstep
.
See theRange
module for more information.
Examples
iex>0in1..3//1falseiex>2in1..3//1trueiex>2in1..3//2falseiex>Enum.to_list(1..3//1)[1,2,3]iex>Enum.to_list(1..3//2)[1,3]iex>Enum.to_list(3..1//-1)[3,2,1]iex>Enum.to_list(1..0//1)[]
Boolean "not" operator.
Receives any value (not just booleans) and returnstrue
ifvalue
isfalse
ornil
; returnsfalse
otherwise.
Not allowed in guard clauses.
Examples
iex>!Enum.empty?([])falseiex>!List.first([])true
Binary concatenation operator. Concatenates two binaries.
Raises anArgumentError
if one of the sides aren't binaries.
Examples
iex>"foo"<>"bar""foobar"
The<>/2
operator can also be used in pattern matching (and guard clauses) aslong as the left argument is a literal binary:
iex>"foo"<>x="foobar"iex>x"bar"
x <> "bar" = "foobar"
would result in anArgumentError
exception.
Text-based match operator. Matches the term on theleft
against the regular expression or string on theright
.
Ifright
is a regular expression, returnstrue
ifleft
matches right.
Ifright
is a string, returnstrue
ifleft
containsright
.
Examples
iex>"abcd"=~~r/c(d)/trueiex>"abcd"=~~r/e/falseiex>"abcd"=~~r//trueiex>"abcd"=~"bc"trueiex>"abcd"=~"ad"falseiex>"abcd"=~"abcd"trueiex>"abcd"=~""true
For more information about regular expressions, please check theRegex
module.
Module attribute unary operator.
Reads and writes attributes in the current module.
The canonical example for attributes is annotating that a moduleimplements an OTP behaviour, such asGenServer
:
defmoduleMyServerdo@behaviourGenServer# ... callbacks ...end
By default Elixir supports all the module attributes supported by Erlang, butcustom attributes can be used as well:
defmoduleMyServerdo@my_data13IO.inspect(@my_data)#=> 13end
Unlike Erlang, such attributes are not stored in the module by default sinceit is common in Elixir to use custom attributes to store temporary data thatwill be available at compile-time. Custom attributes may be configured tobehave closer to Erlang by usingModule.register_attribute/3
.
Prefixing module attributes
Libraries and frameworks should consider prefixing anymodule 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:
defmoduleMyServerdo@my_data11deffirst_data,do:@my_data@my_data13defsecond_data,do:@my_dataendMyServer.first_data()#=> 11MyServer.second_data()#=> 13
It is important to note that reading an attribute takes a snapshot ofits current value. In other words, the value is read at compilationtime and not at runtime. Check theModule
module for other functionsto manipulate module attributes.
Attention! Multiple references of the same attribute
As mentioned above, every time you read a module attribute, a snapshotof its current value is taken. Therefore, if you are storing largevalues inside module attributes (for example, embedding external filesin module attributes), you should avoid referencing the same attributemultiple times. For example, don't do this:
@files%{example1:File.read!("lib/example1.data"),example2:File.read!("lib/example2.data")}defexample1,do:@files[:example1]defexample2,do:@files[:example2]
In the above, each reference to@files
may end-up with a completeand individual copy of the whole@files
module attribute. Instead,reference the module attribute once in a private function:
@files%{example1:File.read!("lib/example1.data"),example2:File.read!("lib/example2.data")}defpfiles(),do:@filesdefexample1,do:files()[:example1]defexample2,do:files()[:example2]
When used inside quoting, marks that the given alias should notbe hygienized. This means the alias will be expanded whenthe macro is expanded.
Checkquote/2
for more information.
Invokes the given anonymous functionfun
with the list ofargumentsargs
.
If the number of arguments is known at compile time, preferfun.(arg_1, arg_2, ..., arg_n)
as it is clearer thanapply(fun, [arg_1, arg_2, ..., arg_n])
.
Inlined by the compiler.
Examples
iex>apply(fnx->x*2end,[2])4
Invokes the given function frommodule
with the list ofargumentsargs
.
apply/3
is used to invoke functions where the module, functionname or arguments are defined dynamically at runtime. For thisreason, you can't invoke macros usingapply/3
, only functions.
If the number of arguments and the function name are known at compile time,prefermodule.function(arg_1, arg_2, ..., arg_n)
as it is clearer thanapply(module, :function, [arg_1, arg_2, ..., arg_n])
.
apply/3
cannot be used to call private functions.
Inlined by the compiler.
Examples
iex>apply(Enum,:reverse,[[1,2,3]])[3,2,1]
Returns a binary from the offset given by the start of therange to the offset given by the end of the range.
If the start or end of the range are negative, they are convertedinto positive indices based on the binary size. For example,-1
means the last byte of the binary.
This is similar tobinary_part/3
except that it works with rangesand it is not allowed in guards.
This function works with bytes. For a slicing operation thatconsiders characters, seeString.slice/2
.
Examples
iex>binary_slice("elixir",0..5)"elixir"iex>binary_slice("elixir",1..3)"lix"iex>binary_slice("elixir",1..10)"lixir"iex>binary_slice("elixir",-4..-1)"ixir"iex>binary_slice("elixir",-4..6)"ixir"iex>binary_slice("elixir",-10..10)"elixir"
For ranges wherestart > stop
, you need to explicitlymark them as increasing:
iex>binary_slice("elixir",2..-1//1)"ixir"iex>binary_slice("elixir",1..-2//1)"lixi"
You can use../0
as a shortcut for0..-1//1
, which returnsthe whole binary as is:
iex>binary_slice("elixir",..)"elixir"
The step can be any positive number. For example, toget every 2 characters of the binary:
iex>binary_slice("elixir",0..-1//2)"eii"
If the first position is after the string ends or afterthe last position of the range, it returns an empty string:
iex>binary_slice("elixir",10..3//1)""iex>binary_slice("elixir",-10..-7)""iex>binary_slice("a",1..1500)""
Returns a binary starting at the offsetstart
and of the givensize
.
This is similar tobinary_part/3
except that ifstart + size
is greater than the binary size, it automatically clips it tothe binary size instead of raising. Opposite tobinary_part/3
,this function is not allowed in guards.
This function works with bytes. For a slicing operation thatconsiders characters, seeString.slice/3
.
Examples
iex>binary_slice("elixir",0,6)"elixir"iex>binary_slice("elixir",0,5)"elixi"iex>binary_slice("elixir",1,4)"lixi"iex>binary_slice("elixir",0,10)"elixir"
Ifstart
is negative, it is normalized against the binarysize and clamped to 0:
iex>binary_slice("elixir",-3,10)"xir"iex>binary_slice("elixir",-10,10)"elixir"
If thesize
is zero, an empty binary is returned:
iex>binary_slice("elixir",1,0)""
Ifstart
is greater than or equal to the binary size,an empty binary is returned:
iex>binary_slice("elixir",10,10)""
Returns the binding for the given context as a keyword list.
In the returned result, keys are variable names and values are thecorresponding variable values.
If the givencontext
isnil
(by default it is), the binding for thecurrent context is returned.
Examples
iex>x=1iex>binding()[x:1]iex>x=2iex>binding()[x:2]iex>binding(:foo)[]iex>var!(x,:foo)=11iex>binding(:foo)[x:1]
Debugs the givencode
.
dbg/2
can be used to debug the givencode
through a configurable debug function.It returns the result of the given code.
Examples
Let's take this call todbg/2
:
dbg(Atom.to_string(:debugging))#=> "debugging"
It returns the string"debugging"
, which is the result of theAtom.to_string/1
call.Additionally, the call above prints:
[my_file.ex:10:MyMod.my_fun/0]Atom.to_string(:debugging)#=> "debugging"
The default debugging function prints additional debugging info when dealing withpipelines. 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. Seebinding/1
.
dbg
inside IEx
You can enable IEx to replacedbg
with itsIEx.pry/0
backend by calling:
$iex --dbg pry
In such cases,dbg
will start apry
session where you can interact withthe imports, aliases, and variables of the current environment at the locationof thedbg
call.
If you calldbg
at the end of a pipeline (using|>
) within IEx, you are ableto go through each step of the pipeline one by one by entering "next" (or "n").
Notedbg
only supports stepping for pipelines (in other words, it can onlystep through the code it sees). For general stepping, you can set breakpointsusingIEx.break!/4
.
For more information,see IEx documentation.
Configuring the debug function
One of the benefits ofdbg/2
is that its debugging logic is configurable,allowing tools to extenddbg
with enhanced behaviour. This is done, forexample, byIEx
which extendsdbg
with an interactive shell where youcan 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. Thefunction
function inmodule
will beinvoked with three argumentsprepended toargs
:
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 debuggedexpression.
Here's a simple example:
defmoduleMyModdodefdebug_fun(code,options,caller,device)doquotedoresult=unquote(code)IO.inspect(unquote(device),result,label:unquote(Macro.to_string(code)))endendend
To configure the debug function:
# In config/config.exsconfig:elixir,:dbg_callback,{MyMod,:debug_fun,[:stdio]}
Default debug function
By default, the debug function we use isMacro.dbg/3
. It just printsinformation about the code to standard output and returns the valuereturned by evaluatingcode
.options
are used to control how termsare inspected. They are the same options accepted byinspect/2
.
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, asum/2
function is defined; this function receivestwo arguments and returns their sum.
Default arguments
\\
is used to specify a default value for a parameter of a function. Forexample:
defmoduleMyMathdodefmultiply_by(number,factor\\2)donumber*factorendendMyMath.multiply_by(4,3)#=> 12MyMath.multiply_by(4)#=> 8
The compiler translates this into multiple functions with different arities,hereMyMath.multiply_by/1
andMyMath.multiply_by/2
, that represent cases whenarguments for parameters with default values are passed or not passed.
When defining a function with default arguments as well as multipleexplicitly declared clauses, you must write a function head that declares thedefaults. For example:
defmoduleMyStringdodefjoin(string1,string2\\nil,separator\\" ")defjoin(string1,nil,_separator)dostring1enddefjoin(string1,string2,separator)dostring1<>separator<>string2endend
Note that\\
can't be used with anonymous functions because theycan only have a sole arity.
Keyword lists with default arguments
Functions containing many arguments can benefit from usingKeyword
lists to group and pass attributes as a single value.
defmoduleMyConfigurationdo@default_opts[storage:"local"]defconfigure(resource,opts\\[])doopts=Keyword.merge(@default_opts,opts)storage=opts[:storage]# ...endend
The difference between usingMap
andKeyword
to store manyarguments isKeyword
'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 aUnicode letter that is not in uppercase or titlecase. They may continueusing a sequence of Unicode letters, numbers, and underscores. They mayend in?
or!
. Elixir'sNaming Conventionssuggest for function and variable names to be written in thesnake_case
format.
rescue
/catch
/after
/else
Function bodies supportrescue
,catch
,after
, andelse
astry/1
does (known as "implicit try"). For example, the following two functions are equivalent:
defconvert(number)dotrydoString.to_integer(number)rescueeinArgumentError->{:error,e.message}endenddefconvert(number)doString.to_integer(number)rescueeinArgumentError->{:error,e.message}end
Defines a function that delegates to another module.
Functions defined withdefdelegate/2
are public and can be invoked fromoutside the module they're defined in, as if they were defined usingdef/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 withoutusing its full module name, then usealias/2
to shorten the module name or useimport/2
to be able to invoke the function without the module name altogether.
Delegation only works with functions; delegating macros is not supported.
Checkdef/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 beingdelegated (funs
).
Examples
defmoduleMyListdodefdelegatereverse(list),to:Enumdefdelegateother_reverse(list),to:Enum,as::reverseendMyList.reverse([1,2,3])#=> [3, 2, 1]MyList.other_reverse([1,2,3])#=> [3, 2, 1]
Defines an exception.
Exceptions are structs backed by a module that implementstheException
behaviour. TheException
behaviour requirestwo functions to be implemented:
exception/1
- receives the arguments given toraise/2
and returns the exception struct. The default implementationaccepts either a set of keyword arguments that is merged intothe struct or a string to be used as the exception's message.message/1
- receives the exception struct and must return itsmessage. Most commonly exceptions have a message field whichby default is accessed by this function. However, if an exceptiondoes not have a message field, this function must be explicitlyimplemented.
Since exceptions are structs, the API supported bydefstruct/1
is also available indefexception/1
.
Raising exceptions
The most common way to raise an exception is viaraise/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 toraise/2
and generate the message in theException.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 customizingexception messages.
Defines a macro suitable for use in guard expressions.
It raises at compile time if theguard
uses expressions that aren'tallowed inguard clauses,and otherwise creates a macro that can be used both inside or outside guards.
When defining your own guards, consider thenaming conventionsaround boolean-returning guards.
Example
defmoduleInteger.Guardsdodefguardis_even(value)whenis_integer(value)andrem(value,2)==0enddefmoduleCollatzdo@moduledoc"Tools for working with the Collatz sequence."importInteger.Guards@doc"Determines the number of steps `n` takes to reach `1`."# If this function never converges, please let me know what `n` you used.defconverge(n)whenn>0,do:step(n,0)defpstep(1,step_count)dostep_countenddefpstep(n,step_count)whenis_even(n)dostep(div(n,2),step_count+1)enddefpstep(n,step_count)dostep(3*n+1,step_count+1)endend
Defines a private macro suitable for use in guard expressions.
It raises at compile time if theguard
uses expressions that aren'tallowed inguard clauses,and otherwise creates a private macro that can be usedboth inside or outside guards in the current module.
When defining your own guards, consider thenaming conventionsaround boolean-returning guards.
Similar todefmacrop/2
,defguardp/1
must be defined before its usein the current module.
Defines an implementation for the given protocol.
See theProtocol
module for more information.
Defines a public macro with the given name and body.
Macros must be defined before its usage.
Checkdef/2
for rules on naming and default arguments.
Examples
defmoduleMyLogicdodefmacrounless(expr,opts)doquotedoif!unquote(expr),unquote(opts)endendendrequireMyLogicMyLogic.unlessfalsedoIO.puts("It works")end
Defines a private macro with the given name and body.
Private macros are only accessible from the same module in which they aredefined.
Private macros must be defined before its usage.
Checkdefmacro/2
for more information, and checkdef/2
for rules onnaming and default arguments.
Defines a module given by name with the given contents.
This macro defines a module with the givenalias
as its name and with thegiven contents. It returns a tuple with four elements:
:module
- the module name
- the binary contents of the module
- the result of evaluating the contents block
Examples
defmoduleNumberdodefone,do:1deftwo,do:2end#=> {:module, Number, <<70, 79, 82, ...>>, {:two, 0}}Number.one()#=> 1Number.two()#=> 2
Module names and aliases
Module names (and aliases) must start with an ASCII uppercase character whichmay be followed by any ASCII letter, number, or underscore. Elixir'sNaming Conventions suggest for module names and aliasesto be written in theCamelCase
format.
You can also use atoms as the module name, although they must only contain ASCIIcharacters.
Nesting
Nesting a module inside another module affects the name of the nested module:
defmoduleFoododefmoduleBardoendend
In the example above, two modules -Foo
andFoo.Bar
- are created.When nesting, Elixir automatically creates an alias to the inner module,allowing the second moduleFoo.Bar
to be accessed asBar
in the samelexical scope where it's defined (theFoo
module). This only happensif the nested module is defined via an alias.
If theFoo.Bar
module is moved somewhere else, the references toBar
intheFoo
module need to be updated to the fully-qualified name (Foo.Bar
) oran alias has to be explicitly set in theFoo
module with the help ofalias/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 veryuseful when working with macros. For instance, one could write:
defmoduleModule.concat(["Foo","Bar"])do# contents ...end
Elixir will accept any module name as long as the expression passed as thefirst argument todefmodule/2
evaluates to an atom.Note that, when a dynamic name is used, Elixir won't nest the name underthe current module nor automatically set up an alias.
Reserved module names
If you attempt to define a module that already exists, you will get awarning saying that a module has been redefined.
There are some modules that Elixir does not currently implement but itmay be implement in the future. Those modules are reserved and definingthem 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
, andReference
.
Makes the given definitions in the current module overridable.
If the user defines a new function or macro with the same nameand arity, then the overridable ones are discarded. Otherwise, theoriginal definitions are used.
It is possible for the overridden definition to have a different visibilitythan the original: a public function can be overridden by a privatefunction and vice-versa.
Macros cannot be overridden as functions and vice-versa.
Example
defmoduleDefaultModdodefmacro__using__(_opts)doquotedodeftest(x,y)dox+yenddefoverridabletest:2endendenddefmoduleChildModdouseDefaultModdeftest(x,y)dox*y+super(x,y)endend
As seen as in the example above,super
can be used to call the defaultimplementation.
Disclaimer
Usedefoverridable
with care. If you need to define multiple moduleswith the same behaviour, it may be best to move the default implementationto the caller, and check if a callback exists viaCode.ensure_loaded?/1
andfunction_exported?/3
.
For example, in the example above, imagine there is a module that calls thetest/2
function. This module could be defined as such:
defmoduleCallsTestdodefreceives_module_and_calls_test(module,x,y)doifCode.ensure_loaded?(module)andfunction_exported?(module,:test,2)domodule.test(x,y)elsex+yendendend
Example with behaviour
You can also pass a behaviour todefoverridable
and it will mark all of thecallbacks in the behaviour as overridable:
defmoduleBehaviourdo@callbacktest(number(),number())::number()enddefmoduleDefaultModdodefmacro__using__(_opts)doquotedo@behaviourBehaviourdeftest(x,y)dox+yenddefoverridableBehaviourendendenddefmoduleChildModdouseDefaultModdeftest(x,y)dox*y+super(x,y)endend
Defines a private function with the given name and body.
Private functions are only accessible from within the module in which they aredefined. Trying to access a private function from outside the module it'sdefined in results in anUndefinedFunctionError
exception.
Checkdef/2
for more information.
Examples
defmoduleFoododefbardosum(1,2)enddefpsum(a,b),do:a+bendFoo.bar()#=> 3Foo.sum(1,2)** (UndefinedFunctionError) undefined function Foo.sum/2
Defines a protocol.
See theProtocol
module for more information.
Defines a struct.
A struct is a tagged map that allows developers to providedefault values for keys, tags to be used in polymorphicdispatches and compile time assertions.
It is only possible to define a struct per module, as thestruct is tied to the module itself.
Examples
defmoduleUserdodefstructname:nil,age:nilend
Struct fields are evaluated at compile-time, which allowsthem to be dynamic. In the example below,10 + 11
isevaluated at compile-time and the age field is storedwith value21
:
defmoduleUserdodefstructname:nil,age:10+11end
Thefields
argument is usually a keyword list with field namesas atom keys and default values as corresponding values.defstruct/1
also supports a list of atoms as its argument: in that case, the atomsin the list will be used as the struct's field names and they will alldefault tonil
.
defmodulePostdodefstruct[:title,:content,:author]end
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 onstructs, please check%/2
.
Deriving
Although structs are maps, by default structs do not implementany of the protocols implemented for maps. For example, attemptingto use a protocol with theUser
struct leads to an error:
john=%User{name:"John"}MyProtocol.call(john)** (Protocol.UndefinedError) protocol MyProtocol not implemented for %User{...}
defstruct/1
, however, allows protocol implementations to bederived. This can be done by defining a@derive
attribute as alist before invokingdefstruct/1
:
defmoduleUserdo@deriveMyProtocoldefstructname:nil,age:nilendMyProtocol.call(john)# it works!
A common example is to@derive
theInspect
protocol to hide certain fieldswhen the struct is printed:
defmoduleUserdo@derive{Inspect,only::name}defstructname:nil,age:nilend
For each protocol in@derive
, Elixir will verify if the protocolhas implemented theProtocol.__deriving__/2
callback. If so,the callback will be invoked and it should define the implementationmodule. Otherwise an implementation that simply points to theAny
implementation is automatically derived. For more information, seeProtocol.derive/3
.
Enforcing keys
When building a struct, Elixir will automatically guarantee all keysbelong 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 begiven when building the struct:
defmoduleUserdo@enforce_keys[:name]defstructname:nil,age:10+11end
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 guaranteeto aid developers when building structs. It is not enforced onupdates and it does not provide any sort of value-validation.
Types
It is recommended to define types for structs. By convention, such a typeis calledt
. To define a struct inside a type, the struct literal syntaxis used:
defmoduleUserdodefstructname:"John",age:25@typet::%__MODULE__{name:String.t(),age:non_neg_integer}end
It is recommended to only use the struct syntax when defining the struct'stype. When referring to another struct, it's better to useUser.t()
instead of%User{}
.
The types of the struct fields that are not included in%User{}
default toterm()
(seeterm/0
).
Structs whose internal structure is private to the local module (patternmatching them or directly accessing their fields should not be allowed) shoulduse the@opaque
attribute. Structs whose internal structure is public shoulduse@type
.
Destructures two lists, assigning each term in theright one to the matching term in the left one.
Unlike pattern matching via=
, if the sizes of the leftand right lists don't match, destructuring simply stopsinstead of raising an error.
Examples
iex>destructure([x,y,z],[1,2,3,4,5])iex>{x,y,z}{1,2,3}
In the example above, even though the right list has more entries than theleft one, destructuring works fine. If the right list is smaller, theremaining elements are simply set tonil
:
iex>destructure([x,y,z],[1])iex>{x,y,z}{1,nil,nil}
The left-hand side supports any expression you would useon the left-hand side of a match:
x=1destructure([^x,y,z],[1,2,3])
The example above will only work ifx
matches the first value in the rightlist. Otherwise, it will raise aMatchError
(like the=
operator woulddo).
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 withreason:normal
. You can also callexit/1
explicitly if youwant to terminate a process but not signal any failure:
exit(:normal)
In case something goes wrong, you can also useexit/1
witha different reason:
exit(:seems_bad)
If the exit reason is not:normal
, all the processes linked to the processthat exited will crash (unless they are trapping exits).
OTP exits
Exits are used by the OTP to determine if a process exited abnormallyor not. The following exits are considered "normal":
exit(:normal)
exit(:shutdown)
exit({:shutdown, term})
Exiting with any other reason is considered abnormal and treatedas 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
usesexit(:shutdown)
when exiting the test process tosignal linked processes, supervision trees and so on to politelyshut down too.
CLI exits
Building on top of the exit signals mentioned above, if theprocess started by the command line exits with any of the threereasons above, its exit is considered normal and the OperatingSystem process will exit with status 0.
It is, however, possible to customize the operating system exitsignal by invoking:
exit({:shutdown,integer})
This will cause the operating system process to exit with the status given byinteger
while signaling all linked Erlang processes to politelyshut down.
Any other exit reason will cause the operating system process to exit withstatus1
and linked Erlang processes to crash.
Returnstrue
ifmodule
is loaded and contains apublicfunction
with the givenarity
, otherwisefalse
.
Note that this function does not load the module in caseit is not loaded. CheckCode.ensure_loaded/1
for moreinformation.
Inlined by the compiler.
Examples
iex>function_exported?(Enum,:map,2)trueiex>function_exported?(Enum,:map,10)falseiex>function_exported?(List,:to_string,1)true
Gets a value and updates a nested data structure via the givenpath
.
This is similar toget_and_update_in/3
, except the path is extractedvia a macro rather than passing a list. For example:
get_and_update_in(opts[:foo][:bar],&{&1,&1+1})
Is equivalent to:
get_and_update_in(opts,[:foo,:bar],&{&1,&1+1})
This also works with nested structs and thestruct.path.to.value
way to specifypaths:
get_and_update_in(struct.foo.bar,&{&1,&1+1})
Note that in order for this macro to work, the complete path must alwaysbe visible by this macro. See the "Paths" section below.
Examples
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>get_and_update_in(users["john"].age,&{&1,&1+1}){27,%{"john"=>%{age:28},"meg"=>%{age:23}}}
Paths
A path may start with a variable, local or remote call, and must befollowed by one or more:
foo[bar]
- accesses the keybar
infoo
; in casefoo
is nil,nil
is returnedfoo.bar
- accesses a map/struct field; in case the field is notpresent, an error is raised
Here are some valid paths:
users["john"][:age]users["john"].ageUser.all()["john"].ageall_users()["john"].age
Here are some invalid ones:
# Does a remote call after the initial valueusers["john"].do_something(arg1,arg2)# Does not access any key or fieldusers
@spec get_and_update_in( structure, keys, (term() | nil -> {current_value, new_value} | :pop)) :: {current_value, new_structure :: structure}when structure:Access.t(), keys: [term(), ...], current_value:Access.value(), new_value:Access.value()
Gets a value and updates a nested structure.
data
is a nested structure (that is, a map, keywordlist, or struct that implements theAccess
behaviour).
Thefun
argument receives the value ofkey
(ornil
ifkey
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 beforebeing returned.new_value
is the new value to be stored underkey
.:pop
, which implies that the current value underkey
should be removed from the structure and returned.
This function uses theAccess
module to traverse the structuresaccording to the givenkeys
, unless thekey
is a function,which is detailed in a later section.
Examples
This function is useful when there is a need to retrieve the currentvalue (or something calculated in function of the current value) andupdate it at the same time. For example, it could be used to read thecurrent age of a user while increasing it by one in one pass:
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>get_and_update_in(users,["john",:age],&{&1,&1+1}){27,%{"john"=>%{age:28},"meg"=>%{age:23}}}
Note the current value given to the anonymous function may benil
.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 threearguments:
- the operation (
:get_and_update
) - the data to be accessed
- a function to be invoked next
This meansget_and_update_in/3
can be extended to provide customlookups. The downside is that functions cannot be stored as keysin 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 allages inside a list:
iex>users=[%{name:"john",age:27},%{name:"meg",age:23}]iex>all=fn:get_and_update,data,next->...>data|>Enum.map(next)|>Enum.unzip()...>endiex>get_and_update_in(users,[all,:age],&{&1,&1+1}){[27,23],[%{name:"john",age:28},%{name:"meg",age:24}]}
If the previous value before invoking the function isnil
,the functionwill receivenil
as a value and must handle itaccordingly (be it by failing or providing a sane default).
TheAccess
module ships with many convenience accessor functions,like theall
anonymous function defined above. SeeAccess.all/0
,Access.key/2
, and others as examples.
Gets a key from the nested structure via the givenpath
, withnil-safe handling.
This is similar toget_in/2
, except the path is extracted viaa 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 returnsnil
, thennil
will be returnedandget_in/1
won't traverse any further.
Note that in order for this macro to work, the complete path must alwaysbe visible by this macro. For more information about the supported pathexpressions, please checkget_and_update_in/2
docs.
Examples
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>get_in(users["john"].age)27iex>get_in(users["unknown"].age)nil
Gets a value from a nested structure with nil-safe handling.
Uses theAccess
module to traverse the structuresaccording to the givenkeys
, unless thekey
is afunction, which is detailed in a later section.
Examples
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>get_in(users,["john",:age])27iex># Equivalent to:iex>users["john"][:age]27
get_in/2
can also use the accessors in theAccess
moduleto traverse more complex data structures. For example, here weuseAccess.all/0
to traverse a list:
iex>users=[%{name:"john",age:27},%{name:"meg",age:23}]iex>get_in(users,[Access.all(),:age])[27,23]
In case any of the components returnsnil
,nil
will be returnedandget_in/2
won't traverse any further:
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>get_in(users,["unknown",:age])niliex># Equivalent to:iex>users["unknown"][:age]nil
Functions as keys
If a key given toget_in/2
is a function, the function will be invokedpassing three arguments:
- the operation (
:get
) - the data to be accessed
- a function to be invoked next
This meansget_in/2
can be extended to provide custom lookups.That's precisely how theAccess.all/0
key in the previous sectionbehaves. For example, we can manually implement such traversal asfollows:
iex>users=[%{name:"john",age:27},%{name:"meg",age:23}]iex>all=fn:get,data,next->Enum.map(data,next)endiex>get_in(users,[all,:age])[27,23]
TheAccess
module ships with many convenience accessor functions.SeeAccess.all/0
,Access.key/2
, and others as examples.
Working with structs
By default, structs do not implement theAccess
behaviour requiredby 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 thestruct.field
notation:
some_struct.some_key.nested_key
However, the code above will fail if any of the values returnnil
.If you also want to handle nil values, you can useget_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 severalfields at once or provide custom return values:
casesome_structdo%{some_key:%{nested_key:value}}->value%{}->nilend
Provides anif/2
macro.
This macro expects the first argument to be a condition and the secondargument to be a keyword list. Generally speaking, Elixir developersprefer to use pattern matching and guards in function definitions andcase/2
, as they are succinct and precise. However, not all conditionscan be expressed through patterns and guards, which makesif/2
a viablealternative.
Similar tocase/2
, any assignment in the condition will be availableon both clauses, as well as after theif
expression.
One-liner examples
if(foo,do:bar)
In the example above,bar
will be returned iffoo
evaluates toa truthy value (neitherfalse
nornil
). Otherwise,nil
will bereturned.
Anelse
option can be given to specify the opposite:
if(foo,do:bar,else:baz)
Blocks examples
It's also possible to pass a block to theif/2
macro. The firstexample above would be translated to:
iffoodobarend
Note thatdo
-end
become delimiters. The second example wouldtranslate to:
iffoodobarelsebazend
If you find yourself nesting conditionals inside conditionals,consider usingcond/1
.
Inspects the given argument according to theInspect
protocol.The second argument is a keyword list with options to controlinspection.
Options
inspect/2
accepts a list of options that are internallytranslated to anInspect.Opts
struct. Check the docs forInspect.Opts
to see the supported options.
Examples
iex>inspect(:foo)":foo"iex>inspect([1,2,3,4,5],limit:3)"[1, 2, 3, ...]"iex>inspect([1,2,3],pretty:true,width:0)"[1,\n 2,\n 3]"iex>inspect("olá"<><<0>>)"<<111, 108, 195, 161, 0>>"iex>inspect("olá"<><<0>>,binaries::as_strings)"\"olá\\0\""iex>inspect("olá",binaries::as_binaries)"<<111, 108, 195, 161>>"iex>inspect(~c"bar")"~c\"bar\""iex>inspect([0|~c"bar"])"[0, 98, 97, 114]"iex>inspect(100,base::octal)"0o144"iex>inspect(100,base::hex)"0x64"
Note that theInspect
protocol does not necessarily return a validrepresentation of an Elixir term. In such cases, the inspected resultmust start with#
. For example, inspecting a function will return:
inspect(fna,b->a+bend)#=> #Function<...>
TheInspect
protocol can be derived to hide certain fieldsfrom structs, so they don't show up in logs, inspects and similar.See the "Deriving" section of the documentation of theInspect
protocol for more information.
Returnstrue
ifmodule
is loaded and contains apublicmacro
with the givenarity
, otherwisefalse
.
Note that this function does not load the module in caseit is not loaded. CheckCode.ensure_loaded/1
for moreinformation.
Ifmodule
is an Erlang module (as opposed to an Elixir module), thisfunction always returnsfalse
.
Examples
iex>macro_exported?(Kernel,:use,2)trueiex>macro_exported?(:erlang,:abs,1)false
@spec make_ref() ::reference()
Returns an almost unique reference.
The returned reference will re-occur after approximately 2^82 calls;therefore it is unique enough for practical purposes.
Inlined by the compiler.
Examples
make_ref()#=> #Reference<0.0.0.135>
A convenience macro that checks if the right side (an expression) matches theleft side (a pattern).
Examples
iex>match?(1,1)trueiex>match?({1,_},{1,2})trueiex>map=%{a:1,b:2}iex>match?(%{a:_},map)trueiex>a=1iex>match?(^a,1)true
match?/2
is very useful when filtering or finding a value in an enumerable:
iex>list=[a:1,b:2,a:3]iex>Enum.filter(list,&match?({:a,_},&1))[a:1,a:3]
Guard clauses can also be given to the match:
iex>list=[a:1,b:2,a:3]iex>Enum.filter(list,&match?({:a,x}whenx<2,&1))[a:1]
Variables assigned in the match will not be available outside of thefunction call (unlike regular pattern matching with the=
operator):
iex>match?(_x,1)trueiex>binding()[]
Values vs patterns
Remember the pin operator matchesvalues, notpatterns.Passing a variable as the pattern will always returntrue
and willresult in a warning that the variable is unused:
# don't do thispattern=%{a::a}match?(pattern,%{b::b})
Similarly, moving an expression out the pattern may no longer preserveits semantics. For example:
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 notonce assigned to a variable:
match?(%{x:1},%{x:1,y:2})#=> trueattrs=%{x:1}match?(^attrs,%{x:1,y:2})#=> false
The pin operator will check if the values are equal, using===/2
, whilepatterns have their own rules when matching maps, lists, and so forth.Such behavior is not specific tomatch?/2
. The following code alsothrows an exception:
attrs=%{x:1}^attrs=%{x:1,y:2}#=> (MatchError) no match of right hand side value: %{x: 1, y: 2}
Returns the biggest of the two given terms according totheir structural comparison.
If the terms compare equal, the first one is returned.
This performs a structural comparison where all Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Inlined by the compiler.
Examples
iex>max(1,2)2iex>max("a","b")"b"
Returns the smallest of the two given terms according totheir structural comparison.
If the terms compare equal, the first one is returned.
This performs a structural comparison where all Elixirterms can be compared with each other. See the"Structuralcomparison" sectionfor more information.
Inlined by the compiler.
Examples
iex>min(1,2)1iex>min("foo","bar")"bar"
Pops a key from the nested structure via the givenpath
.
This is similar topop_in/2
, except the path is extracted viaa 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 alwaysbe visible by this macro. For more information about the supported pathexpressions, please checkget_and_update_in/2
docs.
Examples
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>pop_in(users["john"][:age]){27,%{"john"=>%{},"meg"=>%{age:23}}}iex>users=%{john:%{age:27},meg:%{age:23}}iex>pop_in(users.john[:age]){27,%{john:%{},meg:%{age:23}}}
In case any entry returnsnil
, its key will be removedand the deletion will be considered a success.
@spec pop_in(data, [Access.get_and_update_fun(term(), data) |term(), ...]) :: {term(), data}when data:Access.container()
Pops a key from the given nested structure.
Uses theAccess
protocol to traverse the structuresaccording to the givenkeys
, unless thekey
is afunction. If the key is a function, it will be invokedas specified inget_and_update_in/3
.
Examples
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>pop_in(users,["john",:age]){27,%{"john"=>%{},"meg"=>%{age:23}}}
In case any entry returnsnil
, its key will be removedand the deletion will be considered a success.
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>pop_in(users,["jane",:age]){nil,%{"john"=>%{age:27},"meg"=>%{age:23}}}
@spec put_elem(tuple(),non_neg_integer(),term()) ::tuple()
Putsvalue
at the given zero-basedindex
intuple
.
Inlined by the compiler.
Examples
iex>tuple={:foo,:bar,3}iex>put_elem(tuple,0,:baz){:baz,:bar,3}
Puts a value in a nested structure via the givenpath
.
This is similar toput_in/3
, except the path is extracted viaa 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 thestruct.path.to.value
way to specifypaths:
put_in(struct.foo.bar,:baz)
Note that in order for this macro to work, the complete path must alwaysbe visible by this macro. For more information about the supported pathexpressions, please checkget_and_update_in/2
docs.
Examples
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>put_in(users["john"][:age],28)%{"john"=>%{age:28},"meg"=>%{age:23}}iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>put_in(users["john"].age,28)%{"john"=>%{age:28},"meg"=>%{age:23}}
Puts a value in a nested structure.
Uses theAccess
module to traverse the structuresaccording to the givenkeys
, unless thekey
is afunction. If the key is a function, it will be invokedas specified inget_and_update_in/3
.
Examples
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>put_in(users,["john",:age],28)%{"john"=>%{age:28},"meg"=>%{age:23}}
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
Raises an exception.
Ifmessage
is a string, it raises aRuntimeError
exception with it.
Ifmessage
is an atom, it just callsraise/2
with the atom as the firstargument and[]
as the second one.
Ifmessage
is an exception struct, it is raised as is.
Ifmessage
is anything else,raise
will fail with anArgumentError
exception.
Examples
iex>raise"oops"** (RuntimeError) oopstrydo1+:foorescuexin[ArithmeticError]->IO.puts("that was expected")raisexend
Raises an exception.
Calls theexception/1
function on the given argument (which has to be amodule name likeArgumentError
orRuntimeError
) passingattributes
in order to retrieve the exception struct.
Any module that contains a call to thedefexception/1
macro automaticallyimplements theException.exception/1
callback expected byraise/2
.For more information, seedefexception/1
.
Examples
iex>raise(ArgumentError,"Sample")** (ArgumentError) Sample
Raises an exception preserving a previous stacktrace.
Works likeraise/1
but does not generate a new stacktrace.
Note that__STACKTRACE__
can be used inside catch/rescueto retrieve the current stacktrace.
Examples
trydoraise"oops"rescueexception->reraiseexception,__STACKTRACE__end
Raises an exception preserving a previous stacktrace.
reraise/3
works likereraise/2
, except it passes arguments to theexception/1
function as explained inraise/2
.
Examples
trydoraise"oops"rescueexception->reraiseWrapperError,[exception:exception],__STACKTRACE__end
@spec send(dest ::Process.dest(), message) :: message when message:any()
Sends a message to the givendest
and returns the message.
dest
may be a remote or local PID, a local port, a locallyregistered name, or a tuple in the form of{registered_name, node}
for aregistered name at another node.
For additional documentation, see the!
operator Erlangdocumentation.
Inlined by the compiler.
Examples
iex>send(self(),:hello):hello
Handles the sigil~C
for charlists.
It returns a charlist without interpolations and without escapecharacters.
A charlist is a list of integers where all the integers are valid code points.The three expressions below are equivalent:
~C"foo\n"[?f,?o,?o,?\\,?n][102,111,111,92,110]
In practice, charlists are mostly used in specific scenarios such asinterfacing with older Erlang libraries that do not accept binaries as arguments.
Examples
iex>~C(foo)~c"foo"iex>~C(f#{o}o)~c"f\#{o}o"iex>~C(foo\n)~c"foo\\n"
Handles the sigil~c
for charlists.
It returns a charlist, unescaping characters and replacing interpolations.
A charlist is a list of integers where all the integers are valid code points.The three expressions below are equivalent:
~c"foo"[?f,?o,?o][102,111,111]
In practice, charlists are mostly used in specific scenarios such asinterfacing with older Erlang libraries that do not accept binaries as arguments.
Examples
iex>~c(foo)~c"foo"iex>~c(f#{:o}o)~c"foo"iex>~c(f\#{:o}o)~c"f\#{:o}o"
The list is only printed as a~c
sigil if all code points are within theASCII range:
iex>~c"hełło"[104,101,322,322,111]iex>[104,101,108,108,111]~c"hello"
SeeInspect.Opts
for more information.
Handles the sigil~D
for dates.
By default, this sigil uses the built-inCalendar.ISO
, whichrequires 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 canbe used as long as you follow the representation by a single spaceand the calendar name:
~D[SOME-REPRESENTATION My.Alternative.Calendar]
The lower case~d
variant does not exist as interpolationand escape characters are not useful for date sigils.
More information on dates can be found in theDate
module.
Examples
iex>~D[2015-01-13]~D[2015-01-13]
Handles the sigil~N
for naive date times.
By default, this sigil uses the built-inCalendar.ISO
, whichrequires naive date times to be written in the ISO8601 format:
~N[yyyy-mm-dd hh:mm:ss]~N[yyyy-mm-dd hh:mm:ss.ssssss]~N[yyyy-mm-ddThh:mm:ss.ssssss]
such as:
~N[2015-01-13 13:00:07]~N[2015-01-13T13:00:07.123]
If you are using alternative calendars, any representation canbe used as long as you follow the representation by a single spaceand the calendar name:
~N[SOME-REPRESENTATION My.Alternative.Calendar]
The lower case~n
variant does not exist as interpolationand escape characters are not useful for date time sigils.
More information on naive date times can be found in theNaiveDateTime
module.
Examples
iex>~N[2015-01-13 13:00:07]~N[2015-01-13 13:00:07]iex>~N[2015-01-13T13:00:07.001]~N[2015-01-13 13:00:07.001]
Handles the sigil~r
for regular expressions.
It returns a regular expression pattern, unescaping characters and replacinginterpolations.
More information on regular expressions can be found in theRegex
module.
Examples
iex>Regex.match?(~r/foo/,"foo")trueiex>Regex.match?(~r/a#{:b}c/,"abc")true
While the~r
sigil allows parens and brackets to be used as delimiters,it is preferred to use"
or/
to avoid escaping conflicts with reservedregex characters.
Handles the sigil~S
for strings.
It returns a string without interpolations and without escapecharacters.
Examples
iex>~S(foo)"foo"iex>~S(f#{o}o)"f\#{o}o"iex>~S(\o/)"\\o/"
Handles the sigil~s
for strings.
It returns a string as if it was a double quoted string, unescaping charactersand replacing interpolations.
Examples
iex>~s(foo)"foo"iex>~s(f#{:o}o)"foo"iex>~s(f\#{:o}o)"f\#{:o}o"
Handles the sigil~T
for times.
By default, this sigil uses the built-inCalendar.ISO
, whichrequires 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 canbe used as long as you follow the representation by a single spaceand the calendar name:
~T[SOME-REPRESENTATION My.Alternative.Calendar]
The lower case~t
variant does not exist as interpolationand escape characters are not useful for time sigils.
More information on times can be found in theTime
module.
Examples
iex>~T[13:00:07]~T[13:00:07]iex>~T[13:00:07.001]~T[13:00:07.001]
Handles the sigil~U
to create a UTCDateTime
.
By default, this sigil uses the built-inCalendar.ISO
, whichrequires UTC date times to be written in the ISO8601 format:
~U[yyyy-mm-dd hh:mm:ssZ]~U[yyyy-mm-dd hh:mm:ss.ssssssZ]~U[yyyy-mm-ddThh:mm:ss.ssssss+00:00]
such as:
~U[2015-01-13 13:00:07Z]~U[2015-01-13T13:00:07.123+00:00]
If you are using alternative calendars, any representation canbe used as long as you follow the representation by a single spaceand the calendar name:
~U[SOME-REPRESENTATION My.Alternative.Calendar]
The givendatetime_string
must include "Z" or "00:00" offsetwhich marks it as UTC, otherwise an error is raised.
The lower case~u
variant does not exist as interpolationand escape characters are not useful for date time sigils.
More information on date times can be found in theDateTime
module.
Examples
iex>~U[2015-01-13 13:00:07Z]~U[2015-01-13 13:00:07Z]iex>~U[2015-01-13T13:00:07.001+00:00]~U[2015-01-13 13:00:07.001Z]
Handles the sigil~W
for list of words.
It returns a list of "words" split by whitespace without interpolationsand without escape characters.
Modifiers
s
: words in the list are strings (default)a
: words in the list are atomsc
: words in the list are charlists
Examples
iex>~W(foo #{bar} baz)["foo","\#{bar}","baz"]
Handles the sigil~w
for list of words.
It returns a list of "words" split by whitespace. Character unescaping andinterpolation happens for each word.
Modifiers
s
: words in the list are strings (default)a
: words in the list are atomsc
: words in the list are charlists
Examples
iex>~w(foo#{:bar} baz)["foo","bar","baz"]iex>~w(foo#{" bar baz "})["foo","bar","baz"]iex>~w(--source test/enum_test.exs)["--source","test/enum_test.exs"]iex>~w(foo bar baz)a[:foo,:bar,:baz]iex>~w(foo bar baz)c[~c"foo",~c"bar",~c"baz"]
Spawns the given function and returns its PID.
Typically developers do not use thespawn
functions, instead they useabstractions such asTask
,GenServer
andAgent
, built on top ofspawn
, that spawns processes with more conveniences in terms ofintrospection and debugging.
Check theProcess
module for more process-related functions.
The anonymous function receives 0 arguments, and may return any value.
Inlined by the compiler.
Examples
current=self()child=spawn(fn->send(current,{self(),1+2})end)receivedo{^child,3}->IO.puts("Received 3 back")end
Spawns the given functionfun
from the givenmodule
passing it the givenargs
and returns its PID.
Typically developers do not use thespawn
functions, instead they useabstractions such asTask
,GenServer
andAgent
, built on top ofspawn
, that spawns processes with more conveniences in terms ofintrospection and debugging.
Check theProcess
module for more process-related functions.
Inlined by the compiler.
Examples
spawn(SomeModule,:function,[1,2,3])
Spawns the given function, links it to the current process, and returns its PID.
Typically developers do not use thespawn
functions, instead they useabstractions such asTask
,GenServer
andAgent
, built on top ofspawn
, that spawns processes with more conveniences in terms ofintrospection and debugging.
Check theProcess
module for more process-related functions. For moreinformation on linking, checkProcess.link/1
.
The anonymous function receives 0 arguments, and may return any value.
Inlined by the compiler.
Examples
current=self()child=spawn_link(fn->send(current,{self(),1+2})end)receivedo{^child,3}->IO.puts("Received 3 back")end
Spawns the given functionfun
from the givenmodule
passing it the givenargs
, links it to the current process, and returns its PID.
Typically developers do not use thespawn
functions, instead they useabstractions such asTask
,GenServer
andAgent
, built on top ofspawn
, that spawns processes with more conveniences in terms ofintrospection and debugging.
Check theProcess
module for more process-related functions. For moreinformation on linking, checkProcess.link/1
.
Inlined by the compiler.
Examples
spawn_link(SomeModule,:function,[1,2,3])
Spawns the given function, monitors it and returns its PIDand monitoring reference.
Typically developers do not use thespawn
functions, instead they useabstractions such asTask
,GenServer
andAgent
, built on top ofspawn
, that spawns processes with more conveniences in terms ofintrospection and debugging.
Check theProcess
module for more process-related functions.
The anonymous function receives 0 arguments, and may return any value.
Inlined by the compiler.
Examples
current=self()spawn_monitor(fn->send(current,{self(),1+2})end)
Spawns the given module and function passing the given args,monitors it and returns its PID and monitoring reference.
Typically developers do not use thespawn
functions, instead they useabstractions such asTask
,GenServer
andAgent
, built on top ofspawn
, that spawns processes with more conveniences in terms ofintrospection and debugging.
Check theProcess
module for more process-related functions.
Inlined by the compiler.
Examples
spawn_monitor(SomeModule,:function,[1,2,3])
@spec struct(module() |struct(),Enumerable.t()) ::struct()
Creates and updates a struct.
Thestruct
argument may be an atom (which definesdefstruct
)or astruct
itself. The second argument is anyEnumerable
thatemits two-element tuples (key-value pairs) during enumeration.
Keys in theEnumerable
that don't exist in the struct are automaticallydiscarded. Note that keys must be atoms, as only atoms are allowed whendefining a struct. If there are duplicate keys in theEnumerable
, the lastentry will be taken (same behavior asMap.new/1
).
This function is useful for dynamically creating and updating structs, aswell as for converting maps to structs; in the latter case, just insertingthe appropriate:__struct__
field into the map may not be enough andstruct/2
should be used instead.
Examples
defmoduleUserdodefstructname:"john"endstruct(User)#=> %User{name: "john"}opts=[name:"meg"]user=struct(User,opts)#=> %User{name: "meg"}struct(user,unknown:"value")#=> %User{name: "meg"}struct(User,%{name:"meg"})#=> %User{name: "meg"}# String keys are ignoredstruct(User,%{"name"=>"meg"})#=> %User{name: "john"}
@spec struct!(module() |struct(),Enumerable.t()) ::struct()
Similar tostruct/2
but checks for key validity.
The functionstruct!/2
emulates the compile time behaviorof structs. This means that:
when building a struct, as in
struct!(SomeStruct, key: :value)
,it is equivalent to%SomeStruct{key: :value}
and therefore thisfunction will check if every given key-value belongs to the struct.If the struct is enforcing any key via@enforce_keys
, those willbe enforced as well;when updating a struct, as in
struct!(%SomeStruct{}, key: :value)
,it is equivalent to%SomeStruct{struct | key: :value}
and therefore thisfunction will check if every given key-value belongs to the struct.
Pipes the first argument,value
, into the second argument, a functionfun
,and returnsvalue
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:
%{a:1}|>Map.update!(:a,&&1+2)|>tap(&IO.inspect(&1.a))|>Map.update!(:a,&&1*2)
Pipes the first argument,value
, into the second argument, a functionfun
,and returns the result of callingfun
.
In other words, it invokes the functionfun
withvalue
as argument,and returns its result.
This is most commonly used in pipelines, using the|>/2
operator, allowing youto pipe a value to a function outside of its first argument.
Examples
iex>1|>then(fnx->x*2end)2iex>1|>then(fnx->Enum.drop(["a","b","c"],x)end)["b","c"]
A non-local return from a function.
Usingthrow/1
is generally discouraged, as it allows a functionto escape from its regular execution flow, which can make the codeharder to read. Furthermore, all thrown values must be caught bytry/catch
. Seetry/1
for more information.
Inlined by the compiler.
Converts the given term to a charlist according to theList.Chars
protocol.
Examples
iex>to_charlist(:foo)~c"foo"
Converts the argument to a string according to theString.Chars
protocol.
This is the function invoked when there is string interpolation.
Examples
iex>to_string(:foo)"foo"
@spec to_timeout([{unit,non_neg_integer()}] |timeout() |Duration.t()) ::timeout()when unit: :week | :day | :hour | :minute | :second | :millisecond
Constructs a millisecond timeout from the given components, duration, or timeout.
This function is useful for constructing timeouts to use in functions thatexpecttimeout/0
values (such asProcess.send_after/4
and many others).
Argument
Theduration
argument can be one of aDuration
, atimeout/0
, or a listof components. Each of these is described below.
PassingDuration
s
Duration.t/0
structs can be converted to timeouts. The given duration must haveyear
andmonth
fields set to0
, since those cannot be reliably converted tomilliseconds (due to the varying number of days in a month and year).
Microseconds in durations are converted to milliseconds (throughSystem.convert_time_unit/3
).
Passing components
Theduration
argument can also be keyword list which can contain the followingkeys, 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 bythe corresponding factor.
Passing timeouts
You can also pass timeouts directly to this functions, that is, milliseconds orthe atom:infinity
. In this case, this function just returns the given argument.
Examples
With a keyword list:
iex>to_timeout(hour:1,minute:30)5400000
With a duration:
iex>to_timeout(%Duration{hour:1,minute:30})5400000
With a timeout:
iex>to_timeout(5400000)5400000iex>to_timeout(:infinity):infinity
Provides anunless
macro.
This macro evaluates and returns thedo
block passed in as the secondargument ifcondition
evaluates to a falsy value (false
ornil
).Otherwise, it returns the value of theelse
block if present ornil
if not.
See alsoif/2
.
Examples
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"
Updates a nested structure via the givenpath
.
This is similar toupdate_in/3
, except the path is extracted viaa 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 thestruct.path.to.value
way to specifypaths:
update_in(struct.foo.bar,&(&1+1))
Note that in order for this macro to work, the complete path must alwaysbe visible by this macro. For more information about the supported pathexpressions, please checkget_and_update_in/2
docs.
Examples
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>update_in(users["john"][:age],&(&1+1))%{"john"=>%{age:28},"meg"=>%{age:23}}iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>update_in(users["john"].age,&(&1+1))%{"john"=>%{age:28},"meg"=>%{age:23}}
Updates a key in a nested structure.
Uses theAccess
module to traverse the structuresaccording to the givenkeys
, unless thekey
is afunction. If the key is a function, it will be invokedas specified inget_and_update_in/3
.
data
is a nested structure (that is, a map, keywordlist, or struct that implements theAccess
behaviour).Thefun
argument receives the value ofkey
(ornil
ifkey
is not present) and the result replaces the valuein the structure.
Examples
iex>users=%{"john"=>%{age:27},"meg"=>%{age:23}}iex>update_in(users,["john",:age],&(&1+1))%{"john"=>%{age:28},"meg"=>%{age:23}}
Note the current value given to the anonymous function may benil
.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
Uses the given module in the current context.
When calling:
useMyModule,some::options
Elixir will invokeMyModule.__using__/1
passing the second argument ofuse
as its argument. Since__using__/1
is typically a macro, allthe usual macro rules apply, and its return value should be quoted codethat is then inserted whereuse/2
is called.
Code injection
use MyModule
works as acode-injection point in the caller.Given the caller ofuse MyModule
has little control over how thecode is injected,use/2
should be used with care. If you can,avoid use in favor ofimport/2
oralias/2
whenever possible.
Examples
For example, to write test cases using theExUnit
framework providedwith Elixir, a developer shoulduse
theExUnit.Case
module:
defmoduleAssertionTestdouseExUnit.Case,async:truetest"always pass"doasserttrueendend
In this example, Elixir will call the__using__/1
macro in theExUnit.Case
module with the keyword list[async: true]
as itsargument.
In other words,use/2
translates to:
defmoduleAssertionTestdorequireExUnit.CaseExUnit.Case.__using__(async:true)test"always pass"doasserttrueendend
whereExUnit.Case
defines the__using__/1
macro:
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 thedocumentation forModule
for more information) into the caller.
__using__/1
may also be used to alias, require, or import functionalityfrom different modules:
defmoduleMyModuledodefmacro__using__(_opts)doquotedoimportMyModule.FooimportMyModule.BarimportMyModule.BazaliasMyModule.Repoendendend
However, do not provide__using__/1
if all it does is to import,alias or require the module itself. For example, avoid this:
defmoduleMyModuledodefmacro__using__(_opts)doquotedoimportMyModuleendendend
In such cases, developers should instead import or alias the moduledirectly, so that they can customize those as they wish,without the indirection behinduse/2
. Developers must also avoiddefining functions inside__using__/1
.
Givenuse MyModule
can generate any code, it may not be easy fordevelopers to understand the impact ofuse MyModule
.
For this reason, to provide guidance and clarity, we recommend developersto include an admonition block in their@moduledoc
that explains howuse MyModule
impacts their code. As an example, theGenServer
documentationoutlines:
use GenServer
When youuse GenServer
, theGenServer
module willset@behaviour GenServer
and define achild_spec/1
function, so your module can be used as a childin 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, ifuse 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 blockabove is:
>#### `use GenServer` {: .info}>>Whenyou`useGenServer`,theGenServermodulewill>set`@behaviourGenServer`anddefinea`child_spec/1`>function,soyourmodulecanbeusedasachild>inasupervisiontree.
Marks that the given variable should not be hygienized.
This macro expects a variable and it is typically invokedinsidequote/2
to mark that a variableshould not be hygienized. Seequote/2
for more information.
Examples
iex>Kernel.var!(example)=11iex>Kernel.var!(example)1
Pipe operator.
This operator introduces the expression on the left-hand side asthe first argument to the function call on the right-hand side.
Examples
iex>[1,[2],3]|>List.flatten()[1,2,3]
The example above is the same as callingList.flatten([1, [2], 3])
.
The|>/2
operator is mostly useful when there is a desire to execute a seriesof operations resembling a pipeline:
iex>[1,[2],3]|>List.flatten()|>Enum.map(fnx->x*2end)[2,4,6]
In the example above, the list[1, [2], 3]
is passed as the first argumentto theList.flatten/1
function, then the flattened list is passed as thefirst argument to theEnum.map/2
function which doubles each element of thelist.
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 theEnumerable
protocol is not definedfor 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 functioncall. Therefore, to pipe into an anonymous function, you need toinvoke it:
some_fun=&Regex.replace(~r/l/,&1,"L")"Hello"|>some_fun.()
Alternatively, you can usethen/2
for the same effect:
some_fun=&Regex.replace(~r/l/,&1,"L")"Hello"|>then(some_fun)
then/2
is most commonly used when you want to pipe to a functionbut the value is expected outside of the first argument, such asabove. By replacingsome_fun
by its value, we get:
"Hello"|>then(&Regex.replace(~r/l/,&1,"L"))
Boolean "or" operator.
Provides a short-circuit operator that evaluates and returns the secondexpression only if the first one does not evaluate to a truthy value (that is,it is eithernil
orfalse
). Returns the first expression otherwise.
Not allowed in guard clauses.
Examples
iex>Enum.empty?([1])||Enum.empty?([1])falseiex>List.first([])||truetrueiex>Enum.empty?([1])||11iex>Enum.empty?([])||throw(:bad)true
Note that, unlikeor/2
, this operator accepts any expressionas the first argument, not only booleans.