1# Operators
2
3This document covers operators in Elixir, how they are parsed, how they can be defined, and how they can be overridden.
4
5## Operator precedence and associativity
6
7The following is a list of all operators that Elixir is capable of parsing, ordered from higher to lower precedence, alongside their associativity:
8
9Operator                                              | Associativity
10----------------------------------------------------- | -------------
11`@`                                                   | Unary
12`.`                                                   | Left
13`+` `-` `!` `^` `not` `~~~`                           | Unary
14`*` `/`                                               | Left
15`+` `-`                                               | Left
16`++` `--` `+++` `---` `..` `<>`                       | Right
17`in` `not in`                                         | Left
18`\|>` `<<<` `>>>` `<<~` `~>>` `<~` `~>` `<~>` `<\|>`  | Left
19`<` `>` `<=` `>=`                                     | Left
20`==` `!=` `=~` `===` `!==`                            | Left
21`&&` `&&&` `and`                                      | Left
22`\|\|` `\|\|\|` `or`                                  | Left
23`=`                                                   | Right
24`&`                                                   | Unary
25`=>` (valid only inside `%{}`)                        | Right
26`\|`                                                  | Right
27`::`                                                  | Right
28`when`                                                | Right
29`<-` `\\`                                             | Left
30
31## General operators
32
33Elixir provides the following built-in operators that are defined as functions that can be overridden:
34
35  * [`+`](`+/1`) and [`-`](`-/1`) - unary positive/negative
36  * [`+`](`+/2`), [`-`](`-/2`), [`*`](`*/2`), and [`/`](`//2`) - basic arithmetic operations
37  * [`++`](`++/2`) and [`--`](`--/2`) - list concatenation and subtraction
38  * [`and`](`and/2`) and [`&&`](`&&/2`) - strict and relaxed boolean "and"
39  * [`or`](`or/2`) and [`||`](`||/2`) - strict and relaxed boolean "or"
40  * [`not`](`not/1`) and [`!`](`!/1`) - strict and relaxed boolean "not"
41  * [`in`](`in/2`) and [`not in`](`in/2`) - membership
42  * [`@`](`@/1`) - module attribute
43  * [`..`](`../2`) - range creation
44  * [`<>`](`<>/2`) - binary concatenation
45  * [`|>`](`|>/2`) - pipeline
46  * [`=~`](`=~/2`) - text-based match
47
48Many of those can be used in guards; consult the [list of allowed guard functions and operators](patterns-and-guards.md#list-of-allowed-functions-and-operators).
49
50Additionally, there are a few other operators that Elixir parses but doesn't actually use.
51See [Custom and overridden operators](#custom-and-overridden-operators) below for a list and for guidelines about their use.
52
53Some other operators are special forms and cannot be overridden:
54
55  * [`^`](`^/1`) - pin operator
56  * [`.`](`./2`) - dot operator
57  * [`=`](`=/2`) - match operator
58  * [`&`](`&/1`) - capture operator
59  * [`::`](`Kernel.SpecialForms.::/2`) - type operator
60
61Finally, these operators appear in the precedence table above but are only meaningful within certain constructs:
62
63  * `=>` - see [`%{}`](`%{}/1`)
64  * `when` - see [Guards](patterns-and-guards.md#guards)
65  * `<-` - see [`for`](`for/1`) and [`with`](`with/1`)
66  * `\\` - see [Default arguments](Kernel.html#def/2-default-arguments)
67
68## Comparison operators
69
70Elixir provides the following built-in comparison operators (all of which can be used in guards):
71
72  * [`==`](`==/2`) - equal to
73  * [`===`](`===/2`) - strictly equal to
74  * [`!=`](`!=/2`) - inequal to
75  * [`!==`](`!==/2`) - strictly inequal to
76  * [`<`](`</2`) - less-than
77  * [`>`](`>/2`) - greater-than
78  * [`<=`](`<=/2`) - less-than or equal to
79  * [`>=`](`>=/2`) - greater-than or equal to
80
81The only difference between [`==`](`==/2`) and [`===`](`===/2`) is that [`===`](`===/2`) is strict when it comes to comparing integers and floats:
82
83```elixir
84iex> 1 == 1.0
85true
86iex> 1 === 1.0
87false
88```
89
90[`!=`](`!=/2`) and [`!==`](`!==/2`) act as the negation of [`==`](`==/2`) and [`===`](`===/2`), respectively.
91
92### Term ordering
93
94In Elixir, different data types can be compared using comparison operators:
95
96```elixir
97iex> 1 < :an_atom
98true
99```
100
101The reason we can compare different data types is pragmatism. Sorting algorithms don't need to worry about different data types in order to sort. For reference, the overall sorting order is defined below:
102
103```
104number < atom < reference < function < port < pid < tuple < map < list < bitstring
105```
106
107When comparing two numbers of different types (a number being either an integer or a float), a conversion to the type with greater precision will always occur, unless the comparison operator used is either [`===`](`===/2`) or [`!==`](`!==/2`). A float will be considered more precise than an integer, unless the float is greater/less than +/-9007199254740992.0 respectively, at which point all the significant figures of the float are to the left of the decimal point. This behavior exists so that the comparison of large numbers remains transitive.
108
109The collection types are compared using the following rules:
110
111* Tuples are compared by size, then element by element.
112* Maps are compared by size, then by keys in ascending term order, then by values in key order. In the specific case of maps' key ordering, integers are always considered to be less than floats.
113* Lists are compared element by element.
114* Bitstrings are compared byte by byte, incomplete bytes are compared bit by bit.
115* Atoms are compared using their string value, codepoint by codepoint.
116
117## Custom and overridden operators
118
119### Defining custom operators
120
121Elixir is capable of parsing a predefined set of operators; this means that it's not possible to define new operators (like one could do in Haskell, for example). However, not all operators that Elixir can parse are *used* by Elixir: for example, `+` and `||` are used by Elixir for addition and boolean *or*, but `<~>` is not used (but valid).
122
123To define an operator, you can use the usual `def*` constructs (`def`, `defp`, `defmacro`, and so on) but with a syntax similar to how the operator is used:
124
125```elixir
126defmodule MyOperators do
127  # We define ~> to return the maximum of the given two numbers,
128  # and <~ to return the minimum.
129
130  def a ~> b, do: max(a, b)
131  def a <~ b, do: min(a, b)
132end
133```
134
135To use the newly defined operators, we **have to** import the module that defines them:
136
137```elixir
138iex> import MyOperators
139iex> 1 ~> 2
1402
141iex> 1 <~ 2
1421
143```
144
145The following is a table of all the operators that Elixir is capable of parsing, but that are not used by default:
146
147  * `|||`
148  * `&&&`
149  * `<<<`
150  * `>>>`
151  * `<<~`
152  * `~>>`
153  * `<~`
154  * `~>`
155  * `<~>`
156  * `<|>`
157  * `+++`
158  * `---`
159  * `~~~`
160
161The following operators are used by the `Bitwise` module when imported: [`&&&`](`Bitwise.&&&/2`), [`<<<`](`Bitwise.<<</2`), [`>>>`](`Bitwise.>>>/2`), [`|||`](`Bitwise.|||/2`), [`~~~`](`Bitwise.~~~/1`). See the documentation for `Bitwise` for more information.
162
163Note the Elixir community generally discourages custom operators. They can be hard to read and even more to understand, as they don't have a descriptive name like functions do. That said, some specific cases or custom domain specific languages (DSLs) may justify these practices.
164
165It is also possible replace predefined operators, such as `+`, but doing so is extremely discouraged.
166