> For the complete Mojo documentation index, see [llms.txt](/llms.txt).
> Markdown versions of all pages are available by appending .md to any URL (e.g. /docs/manual/basics.md).

# Mojo operator reference

## Precedence table

<!-- Source: ParserBase.h Precedence enum and -->
<!-- ParserExprs.cpp InfixInfo::get -->

Operator precedence and associativity. Higher-precedence operators bind
tighter. Unless noted, operators associate left to right.

### From highest to lowest precedence

| Precedence | Operators                   | Notes                             |
|------------|-----------------------------|-----------------------------------|
| 1          | `()` `[]` `.`               | Call, subscript, attribute        |
| 2          | `**`                        | Exponentiation, right-associative |
| 3          | `+x` `-x` `~x`              | Unary prefix                      |
| 4          | `*` `@` `/` `//` `%`        | Multiplicative                    |
| 5          | `+` `-`                     | Additive (addition, subtraction)  |
| 6          | `<<` `>>`                   | Bitwise shift (left, right)       |
| 7          | `&`                         | Bitwise AND                       |
| 8          | `^`                         | Bitwise XOR (not transfers)       |
| 9          | `\|`                        | Bitwise OR                        |
| 10         | `==` `!=` `<` `<=` `>` `>=` | Comparisons, chainable            |
| 10         | `in` `not in`               | Membership, chainable             |
| 10         | `is` `is not`               | Identity, chainable               |
| 11         | `not`                       | Boolean NOT, prefix               |
| 12         | `and`                       | Boolean AND, short-circuits       |
| 13         | `or`                        | Boolean OR, short-circuits        |
| 14         | `if`-`else`                 | Ternary, right-associative        |
| 15         | `:=`                        | Walrus operator                   |

_Prefix operators_: positive (`+x`), negative (`-x`), bitwise NOT
complement (`~x`)

_Multiplicative operators_: times (`*`), matrix multiplication (`@`),
divide (`/`, integer types round towards zero), truncating divide (`//`,
integer types round towards negative infinity), modulo (`%`).

_Comparison operators_: equality (`==`), inequality (`!=`), less-than (`<`),
less-than-or-equal (`<=`), greater-than (`>`), greater-than-or-equal (`>=`)

:::note
Assignment operators (`=` `+=` `-=` `*=` `/=` `//=` `%=`
`**=` `@=` `&=` `\|=` `^=` `<<=` `>>=`) are statements,
not expressions. They are not part of expression precedence.
:::

## Right-associative operators

Most operators are left-associative. For example, `a - b + c` groups as
`(a - b) + c`. Two infix operators are right-associative: exponentiation
(`a ** b`) and Mojo's ternary `if`-`else`.

### Exponentiation (`**`)

```mojo
2 ** 3 ** 4
```

groups as

```mojo
2 ** (3 ** 4)
```

Equivalent to `pow(2, 81)`. In Mojo `pow(a, b)` and `a ** b` are
interchangeable.

### Ternary (`if`-`else`)

```mojo
"low" if value < 10 else "high" if value > 100 else "mid"
```

groups as

```mojo
"low" if value < 10 else ("high" if value > 100 else "mid")
```

## Chaining operations

All comparison operators can be chained:

```mojo
a < b < c        # equivalent to: (a < b) and (b < c)
a == b == c      # equivalent to: (a == b) and (b == c)
a < b == c       # equivalent to: (a < b) and (b == c)
a < b <= c != d  # equivalent to: (a < b) and (b <= c) and (c != d)
```

Each intermediate value is evaluated once.

- Chaining only applies between operators at the same precedence. `2 ** 3
  == 8` isn't a chain. It evaluates as `(2 ** 3) == 8` since
  exponentiation binds tighter than comparison.

- Comparison, membership, and identity operators share the same
  precedence and chain together. `5 != a < b in c` is valid and evaluates
  as `(5 != a) and (a < b) and (b in c)`.

## Implementing operators for custom types

Mojo doesn't limit operators use to built-in types. Each operator has
a set of dunder methods your custom types can implement. Once added,
you can use operators in code instead of calling methods.

### Infix operator method types

Each infix operator has up to three forms that decide which operand's
method will run. For `a op b`:

- _Forward_: Mojo tries the forward method first. `a + b` calls
  `a.__add__(b)`.
- _Reversed_: If the forward method doesn't exist or can't handle `b`'s
  type, Mojo falls back to the reversed method on `b`. `a + b` calls
  `b.__radd__(a)`.
- _In-place_: Called for compound assignment. `a += b` calls
  `a.__iadd__(b)`.

For example, if `a` uses a `CustomVector` type:

- `a + 5`: calls the forward method `a.__add__(5)`
- `5 + a`: Int doesn't know custom types. Falls back to the reversed
  method, `a.__radd__(5)`
- `a += 5`: calls the in-place `a.__iadd__(5)` method

### Arithmetic

Implement the methods directly on your struct to use `instance OP
instance`, `instance OP= instance`.

| Operator | Forward        | Reversed          | In-place          |
|----------|----------------|-------------------|-------------------|
| `+`      | `__add__()`    | `__radd__()`      | `__iadd__()`      |
| `-`      | `__sub__()`    | `__rsub__()`      | `__isub__()`      |
| `*`      | `__mul__()`    | `__rmul__()`      | `__imul__()`      |
| `/`      | `__truediv__`  | `__rtruediv__()`  | `__itruediv__()`  |
| `//`     | `__floordiv__` | `__rfloordiv__()` | `__ifloordiv__()` |
| `%`      | `__mod__()`    | `__rmod__()`      | `__imod__()`      |
| `**`     | `__pow__()`    | `__rpow__()`      | `__ipow__()`      |
| `@`      | `__matmul__()` | `__rmatmul__()`   | `__imatmul__()`   |

`__pow__()` and `__ipow__()` accept an optional third argument
  (modulus).

In-place operators are syntactic sugar for the operator applied to the
variable with assignment:

```mojo
x += y     # x = x + y
x -= y     # x = x - y
x *= y     # x = x * y
x /= y     # x = x / y
x //= y    # x = x // y
x %= y     # x = x % y
x **= y    # x = x ** y
x @= y     # x = x @ y
```

**Traits:**

[`Powable`](/docs/std/math/math/Powable/) requires `__pow__()`, doesn't
provide a default.

### Bitwise

Implement the methods directly on your struct to use `a OP
b`, `a OP= b`.

| Operator | Forward        | Reversed        | In-place        |
|----------|----------------|-----------------|-----------------|
| `&`      | `__and__()`    | `__rand__()`    | `__iand__()`    |
| `\|`     | `__or__()`     | `__ror__()`     | `__ior__()`     |
| `^`      | `__xor__()`    | `__rxor__()`    | `__ixor__()`    |
| `<<`     | `__lshift__()` | `__rlshift__()` | `__ilshift__()` |
| `>>`     | `__rshift__()` | `__rrshift__()` | `__irshift__()` |

Bitwise operators are typically implemented on integer and flag types. Like
arithmetic operators, in-place bitwise operators are syntactic sugar for
the operator applied to the variable with assignment:

```mojo
x &= y     # x = x & y
x |= y     # x = x | y
x ^= y     # x = x ^ y
x <<= y    # x = x << y
x >>= y    # x = x >> y
```

### Unary operators

Implement the methods directly on your struct to support
prefix operators like `-x`, `+x`, and `~x`.

| Operator | Method         |
|----------|----------------|
| `-x`     | `__neg__()`    |
| `+x`     | `__pos__()`    |
| `~x`     | `__invert__()` |

Mojo offers one postfix unary operator.

| Operator | Method                       |
|----------|------------------------------|
| `x^`     | Compiler implementation only |

Use the `^` sigil for ownership transfer. `consume(a^)` transfers
ownership of `a` to the `consume` function.

- If the `consume` argument uses the `var` convention, the transfer moves
  the value.
- If not, the value is copied and the original is left intact.

After transfer, the `a` variable is uninitialized. You can't re-use the
name until it's assigned a new value.

```mojo
consume(a^) # transfers ownership of `a`'s value, leaving `a` uninitialized
```

**Disambiguation:** `^` means XOR when followed by a value, and transfer
when used directly after a variable name.

```mojo
a ^ b   # XOR
a^      # transfer
```

### Comparison operators

Implement the methods directly on your struct to use
`a OP b`.

| Operator | Method     | Trait        | Default? |
|----------|------------|--------------|----------|
| `==`     | `__eq__()` | `Equatable`  | Yes      |
| `!=`     | `__ne__()` | `Equatable`  | Yes      |
| `<`      | `__lt__()` | `Comparable` | No       |
| `<=`     | `__le__()` | `Comparable` | Yes      |
| `>`      | `__gt__()` | `Comparable` | Yes      |
| `>=`     | `__ge__()` | `Comparable` | Yes      |

**Traits:**

[`Equatable`](/docs/std/builtin/comparable/Equatable/) provides
`__eq__()` if all your struct's fields conform to `Equatable` using
pairwise field comparison. `__ne__()` derives from `__eq__()`.

[`Comparable`](/docs/std/builtin/comparable/Comparable/) provides
`__le__()`, `__gt__()`, and `__ge__()`, all derived from `__lt__()` and
`__eq__()`. You implement `__lt__()`.

`Comparable` refines `Equatable`, so conforming to
`Comparable` requires both traits. If all your fields are
`Equatable`, you implement `__lt__()` at a minimum.

### Identity and membership operators

Implement the methods directly on your struct to use `a OP b`.

| Operator | Method           | Trait          | Default? |
|----------|------------------|----------------|----------|
| `is`     | `__is__()`       | `Identifiable` | No       |
| `is not` | `__isnot__()`    | `Identifiable` | Yes      |
| `in`     | `__contains__()` | —              | No       |
| `not in` | `__contains__()` | —              | No       |

`x in collection` calls `collection.__contains__(x)`. The method is on
the **container**, not the element. `not in` calls the same method and
negates the result.

`is` tests object identity, not equality. Stdlib types that implement
it include `ArcPointer`, `PythonObject`, and `Optional` (for `is None`
checks).

**Traits:**

[`Identifiable`](/docs/std/builtin/identifiable/Identifiable/) requires
`__is__()`. `__isnot__()` is provided (calls `not (self is rhs)`).

### Subscript operators

Implement the methods directly on your struct to use `a[key]`
reads and `a[key] = b` assigns.

| Operation                | Method          |
|--------------------------|-----------------|
| `obj[key]` (read)        | `__getitem__()` |
| `obj[key] = val` (write) | `__setitem__()` |

Both accept variadic arguments (for multi-dimensional indexing).
