# Operators

Almost every contract operates on data: transforms some values into another. Scope may vary, but operators lay in core of such modifications.

This page lists all the operators in Tact in decreasing order of their precedence, with examples of usage.

Note, that there are no implicit type conversions in Tact, so operators can't be used to, say, add values of different type or compare them in terms of equality without explicitly casting to the same type. That's done with certain functions from the standard library. See `Int.toString()`

for an example of such function.

## Table of operators

The following table lists operators in order of decreasing precedence: from highest to lowest.

Brief description | Operators |
---|---|

Parentheses | `()` |

Unary postfix | `!!` |

Unary prefix | `+` `-` `!` `~` |

Multiplicative | `*` `/` `%` |

Additive | `+` `-` |

Shift | `>>` `<<` |

Relation | `>` `>=` `<` `<=` |

Equality | `==` `!=` |

Bitwise AND | `&` |

Bitwise XOR | `^` |

Bitwise OR | `|` |

Logical AND | `&&` |

Logical OR | `||` |

Ternary | `?:` |

Assignment | `=` and all augmented assignment operators |

## Precedence

All operators on this page are given in order of decreasing precedence, from highest to lowest. Precedence is used to choose which operator would be considered in a particular situation. Whenever any ambiguity arises, Tact would prefer operators with higher precedence over those with lower.

For example, minus sign (`-`

) may be considered as a subtraction operator or as a negation operator, which reverses the sign of the expression from plus to minus, or vice-versa. As the latter has the higher precedence over the former in cases of ambiguity between the two Tact will first consider `-`

as a negation operator. And if that doesn't make sense for the given expression, only then it would consider it as a subtraction operator.

Consider the following code:

```
5 + -5; // here, the minus sign would be viewed as a negation operator
5 -5; // while here it would be viewed as a subtraction operator, despite formatting
```

Even though this example may be simple, neglecting of precedence rules can often lead to confusing situations with operators. The correct order of operations can be ensured by wrapping every operation in parentheses, since parentheses have the highest precedence of all expressions and operators there is.

## Parentheses, `()`

Parentheses (also can be called round brackets, `()`

) are more of a punctuation symbols than actual operators, but their precedence is higher than precedence of any other operator. Use parentheses to override order of operations:

```
5 * 5 - 2; // 23
5 * (5 - 2); // 15
```

## Unary

Unary here means that they are applied only to one operand of the given expression. All unary operators, except for the non-null assertion, are of the same precedence.

Unary operators can be one of the two types:

- prefix — placed before the expression.
- postfix (or suffix) — placed after the expression.

### Non-null assert, `!!`

Unary double-exclamation mark (*non-null assertion*) operator `!!`

is a postfix operator, which enforces non-null values and allows direct access to the value of the optional variable if it's not `null`

. Raises a compilation error otherwise. Can be applied to any optional variable regardless of its non-null type.

Read more about optional variables and fields here: Optionals

### Plus, `+`

Although unary plus sign operator `+`

is specified in the grammar of Tact compiler, it only exists as a binary operator.

### Negate, `-`

Unary minus sign (*negation*) operator `-`

is a prefix operator, which reverses the sign of the expression. Can only be applied to values of type `Int`

:

```
let five: Int = 5;
five + -five; // here, the minus sign is a negation operator, not a subtraction operator
-(-1); // double application gives back the original value, which is 1
--1; // 1
```

### Inverse, `!`

Unary exclamation mark (*inversion*) operator `!`

is a prefix operator, which inverts the boolean value of the expression — changes `true`

to `false`

, and vice versa. Can only be applied to values of type `Bool`

:

```
let iLikeTact: Bool = true;
!iLikeTact; // false
!false; // true
!(!false); // false
!!false; // false
```

### Bitwise NOT, `~`

Unary tilde (*bitwise not*) operator `~`

is a prefix operator, which inverts or *flips* each bit in the binary representation of the expression — changes each $1$ to $0$, and vice versa. Can only be applied to values of type `Int`

:

```
let answer: Int = 42;
~answer; // -43
~(~answer); // 42
~(~0); // 0
~~0; // 0
```

## Binary

Binary operators are split into several subsections, in order of decreasing precedence. Operators within each subsection have the same precedence as the subsection itself.

### Multiplication

Multiply, divide or obtain a remainder.

#### Multiply, `*`

Binary asterisk (*multiplication*) operator `*`

is used for multiplication of two values. Can cause integer overflows.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two * two; // 4
0 * 1_000_000_000; // 0
-1 * 5; // -5
pow(2, 255) * pow(2, 255); // build error: integer overflow!
```

#### Divide, `/`

Binary slash (*division*) operator `/`

is used for integer division of two values, which truncates towards zero if result is positive, and away from zero if result is negative. This is also called rounding down (opens in a new tab) (or rounding towards $-∞$).

An attempt to divide by zero would result in an error with exit code 4: `Integer overflow`

.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two / 2; // 1
two / 1; // 2
-1 / 5; // -1
-1 / -5; // 0
1 / -5; // -1
1 / 5; // 0
6 / 5; // 1, rounding down
-6 / 5; // -2, rounding down (towards -∞)
```

Note that the following relationship between the division and modulo operators always holds for `Int`

type:

```
a / b * b + a % b == a; // true for any Int values of `a` and `b`,
// except when `b` is equal to 0 and we divide `a` by 0,
// which is an attempt to divide by zero resulting in an error
```

#### Modulo, `%`

Binary percent sign (*modulo*) operator `%`

is used for getting the modulo of an integer division, which must not be confused with getting a remainder. For two values of the same sign, modulo and remainder operations are equivalent, but when the operands are of different signs, the modulo result always has the same sign as the *divisor* (value on the right), while the remainder has the same sign as the *dividend* (value on the left), which can make them differ by one unit of the *divisor*.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two % 2; // 0
two % 1; // 1
1 % 5; // 1
-1 % 5; // 4
1 % -5; // -4
-1 % -5; // -1
```

The simplest way to avoid confusion between the two is to prefer using positive values via `abs(x: Int)`

:

`abs(-1) % abs(-5); // 1`

Did you know, that in JavaScript `%`

works as a *remainder* operator, but not *modulo* operator (like in Tact)?

Remainder (%) - JavaScript (opens in a new tab)

Modulo - Wikipedia (opens in a new tab)

### Addition

Add or subtract.

#### Add, `+`

Binary plus (*addition*) operator `+`

is used for adding numbers together. Going beyond the maximum value of an `Int`

will result in an error with exit code 4: `Integer overflow`

.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two + 2; // 4
-1 + 1; // 0
pow(2, 254) + pow(2, 254); // 2 * 2^254
pow(2, 255) + pow(2, 255); // build error: integer overflow!
pow(2, 255) - 1 + pow(2, 255); // 2^256 - 1, maximal value of any integer in Tact!
```

#### Subtract, `-`

Binary minus (*subtraction*) operator `-`

is used for subtracting numbers from each other. Going beyond the minimum value of an `Int`

will result in an error with exit code 4: `Integer overflow`

.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two - 2; // 0
-1 - 1; // -2
pow(2, 254) - pow(2, 254); // 0
pow(2, 255) - pow(2, 255); // 0
pow(2, 256) - pow(2, 256); // build error: integer overflow!
```

### Bitwise shifts

Shift bits to the left or to the right.

#### Shift right, `>>`

Binary double greater than (*bitwise shift right*) operator `>>`

returns an integer which binary representation is the *left operand* value shifted by the *right operand* number of bits to the right. Excess bits shifted off to the right are discarded, and copies of the leftmost bit are shifted in from the left. This operation is also called "sign-propagating right shift" or "arithmetic right shift", because the sign of the resulting number is the same as the sign of the *left operand*. This is a more effective way to divide the *left operand* by $2^n$, where $n$ is equal to the *right operand*.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two >> 1; // 1
4 >> 1; // 2
5 >> 1; // 2, due to flooring of integer values
pow(2, 254) >> 254; // 1
```

#### Shift left, `<<`

Binary double greater than (*bitwise shift left*) operator `<<`

returns an integer which binary representation is the *left operand* value shifted by the *right operand* number of bits to the left. Excess bits shifted off to the left are discarded, and zero bits are shifted in from the right. This is a more effective way to multiply the *left operand* by $2^n$, where $n$ is equal to the *right operand*. Going beyond the maximum value of an `Int`

will result in an error with exit code 4: `Integer overflow`

.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two << 1; // 4
1 << 5; // 1 * 2^5, which is 32
2 << 5; // 2 * 2^5, which is 64
pow(2, 254) == (1 << 254); // true
pow(2, 254) == 1 << 254; // true, no parentheses needed due to higher precedence of >> over ==
pow(2, 255) == 1 << 255; // true, but we're very close to overflow here!
```

### Relation

Find bigger, smaller or equal values.

#### Greater than, `>`

Binary *greater than* operator `>`

returns `true`

if the left operand is greater than the right operand, and `false`

otherwise. Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two > 2; // false
-1 > -3; // true
```

#### Greater than or equal to, `>=`

Binary *greater than or equal to* operator `>=`

returns `true`

if the left operand is greater than or to the right operand, and `false`

otherwise. Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two >= 2; // true
-1 >= -3; // true
```

#### Less than, `<`

Binary *less than* operator `<`

returns `true`

if the left operand is less than the right operand, and `false`

otherwise. Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two < 2; // false
-1 < -3; // false
```

#### Less than or equal to, `<=`

Binary *less than or equal to* operator `<=`

returns `true`

if the left operand is less than or equal to the right operand, and `false`

otherwise. Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two <= 2; // true
-1 <= -3; // false
```

### Equality and inequality, `==`

`!=`

Binary equality (*equal*) operator `==`

checks whether its two operands are *equal*, returning a result of type `Bool`

.

Binary inequality (*not equal*) operator `!=`

checks whether its two operands are *not equal*, returning a result of type `Bool`

.

Both operators require operands to be of the same type and both don't perform implicit type conversions, except for the `Cell`

and `Slice`

types, which are implicitly compared by their hashes.

Both operators can be applied to the following list of types and values:

`Int`

`Bool`

`Address`

`Cell`

, implicitly compares via`.hash()`

`Slice`

, implicitly compares via`.hash()`

`String`

`map<K, V>`

, but only if their key and value types are identical- Optionals and
`null`

value

```
// Int:
2 == 3; // false
2 != 3; // true
// Bool:
true == true; // true
false != true; // true
// Address:
myAddress() == myAddress(); // true
myAddress() != myAddress(); // false
// Cell:
emptyCell() == emptyCell(); // true
emptyCell() != emptyCell(); // false
// Slice:
"A".asSlice() == "A".asSlice(); // true
"A".asSlice() != "A".asSlice(); // false
// String:
"A" == "A"; // true
"A" != "A"; // false
// map<K, V>:
let map1: map<Int, Int> = emptyMap();
let map2: map<Int, Int> = emptyMap();
map1 == map2; // true
map1 != map2; // false
// Optionals and null values themselves
let nullable: Int? = null;
nullable == null; // true
null == null; // true
nullable != null; // false
null != null; // false
let anotherNullable: Int? = 5;
nullable == anotherNullable; // false
nullable != anotherNullable; // true
```

### Bitwise AND, `&`

Binary ampersand (*bitwise AND*) operator `&`

applies a bitwise AND (opens in a new tab), which performs the logical AND operation on each pair of the corresponding bits of operands. This is useful when we want to clear selected bits off a number, where each bit represents an individual flag or a boolean state, which makes it possible to "store" up to $257$ boolean values per integer, as all integers in Tact are $257$-bit signed.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two & 1; // 0
4 & 1; // 0
3 & 1; // 1
1 & 1; // 1
255 & 0b00001111; // 15
0b11111111 & 0b00001111; // 15
```

### Bitwise XOR, `^`

Binary caret (*bitwise XOR*) operator `^`

applies a bitwise XOR (opens in a new tab), which performs the logical exclusive OR (opens in a new tab) operation on each pair of the corresponding bits of operands. The result in each position is $1$ if only one of the bits is $1$, but will be $0$ if both are $0$ or both are $1$. In this it performs the comparison of two bits, giving $1$ if the two bits are different, and $0$ if they are the same.

It is useful for inverting selected bits of an operand (also called toggle or flip), as any bit may be toggled by "XORing" it with $1$.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two ^ 3; // 1
4 ^ 1; // 0
3 ^ 1; // 3
1 ^ 1; // 0
255 ^ 0b00001111; // 240
0b11111111 ^ 0b00001111; // 240
```

### Bitwise OR, `|`

Binary bar (*bitwise OR*) operator `|`

applies a bitwise OR (opens in a new tab), which performs the logical OR operation on each pair of the corresponding bits of operands. This is useful when we want to apply a specific bitmask (opens in a new tab).

For example, *bitwise OR* is commonly used in Tact to combine base modes with optional flags by masking specific bits to $1$ in order to construct a target message `mode`

.

Can only be applied to values of type `Int`

:

```
let two: Int = 2;
two | 1; // 3
4 | 1; // 5
3 | 1; // 3
1 | 1; // 1
255 | 0b00001111; // 255
0b11111111 | 0b00001111; // 255
```

### Logical AND, `&&`

Binary logical AND (logical conjunction (opens in a new tab)) operator `&&`

returns `true`

if both operands are `true`

, and `false`

otherwise. It's short-circuited, meaning that it would immediately evaluate the whole expression as `false`

if the left operand is `false`

, without evaluating the right one.

Can only be applied to values of type `Bool`

:

```
let iLikeTact: Bool = true;
iLikeTact && true; // true, evaluated both operands
iLikeTact && false; // false, evaluated both operands
false && iLikeTact; // false, didn't evaluate iLikeTact
```

### Logical OR, `||`

Binary logical OR (logical disjunction (opens in a new tab)) operator `||`

returns `false`

only if both operands are `false`

, and `true`

otherwise. It's short-circuited, meaning that it would immediately evaluate the whole expression as `true`

if the left operand is `true`

, without evaluating the right one.

Can only be applied to values of type `Bool`

:

```
let iLikeSnails: Bool = false;
iLikeSnails || true; // true, evaluated both operands
iLikeSnails || false; // false, evaluated both operands
true || iLikeSnails; // true, didn't evaluate iLikeSnails
```

## Ternary, `?:`

Conditional (*ternary*) operator is the only Tact operator that takes three operands: a condition followed by a question mark (`?`

), then an expression to execute if the condition is evaluated to `true`

followed by a colon (`:`

), and finally the expression to execute if the condition is evaluated to `false`

. This operator is frequently used as an alternative to an `if...else`

statement.

Condition must resolve to type `Bool`

:

```
// condition
// ↓
true ? "incredibly so" : "absolutely not"; // "incredibly so"
// --------------- ----------------
// ↑ ↑
// | alternative, when condition is false
// |
// consequence, when condition is true
2 + 2 == 4 ? true : false; // true
```

Ternary operator is the only operator with right associativity, besides assignment-related ones. This means that in ambiguous situations Tact would prefer the longest matching sequence. In short, this makes bracket-less nesting of ternary operators possible, but only for alternative cases (the part that comes after the colon sign `:`

):

```
// don't need additional parentheses for alternative cases
false ? 1 : (false ? 2 : 3); // 3
false ? 1 : false ? 2 : 3; // also 3
false ? 1 : true ? 2 : 3; // 2
// need additional parentheses for consequence cases (parts in-between ? and :)
false ? (false ? 1 : 2) : 3; // 3
false ? false ? 1 : 2 : 3; // SYNTAX ERROR!
true ? (false ? 1 : 2) : 3; // 2
```

## Assignment, `=`

Assignment operator `=`

is used to assign a value to a variable, or to a property of a Message or a Struct. The assignment is a statement and it doesn't return a value.

```
let someVar: Int = 5; // assignment operator = is used here...
someVar = 4; // ...and here
someVar = (someVar = 5); // SYNTAX ERROR!
```

### Augmented assignment

Augmented (or compound) assignment operators such as `+=`

combine an operation with an assignment. The augmented assignment is a statement and it doesn't return a value.

Augmented assignments are semantically equivalent to regular assignments, but with an operation:

```
let value: Int = 5;
// this:
value += 5;
// is equivalent to this:
value = value + 5;
```

List of augmented assignment operators:

`+=`

, which uses addition operator`+`

. Can only be applied to values of type`Int`

.`-=`

, which uses subtraction operator`-`

. Can only be applied to values of type`Int`

.`*=`

, which uses multiplication operator`*`

. Can only be applied to values of type`Int`

.`/=`

, which uses division operator`/`

. Can only be applied to values of type`Int`

.`%=`

, which uses modulo operator`%`

. Can only be applied to values of type`Int`

.`&=`

, which uses bitwise AND operator`&`

. Can only be applied to values of type`Int`

.`^=`

, which uses bitwise XOR operator`^`

. Can only be applied to values of type`Int`

.`|=`

, which uses bitwise OR operator`|`

. Can only be applied to values of type`Int`

.

```
let value: Int = 5;
// +=
value + 5; // adds 5
value = value + 5; // adds 5 and assigns result back
value += 5; // also adds 5 and assigns result back
// -=
value - 5; // subtracts 5
value = value - 5; // subtracts 5 and assigns result back
value -= 5; // also subtracts 5 and assigns result back
// *=
value * 5; // multiplies by 5
value = value * 5; // multiplies by 5 and assigns result back
value *= 5; // also multiplies by 5 and assigns result back
// /=
value / 5; // divides by 5
value = value / 5; // divides by 5 and assigns result back
value /= 5; // also divides by 5 and assigns result back
// %=
value % 5; // gets modulo by 5
value = value % 5; // gets modulo by 5 and assigns result back
value %= 5; // also gets modulo by 5 and assigns result back
// &=
value & 5; // bitwise ANDs 5
value = value & 5; // bitwise ANDs 5 and assigns result back
value &= 5; // also bitwise ANDs 5 and assigns result back
// ^=
value ^ 5; // bitwise XORs 5
value = value ^ 5; // bitwise XORs 5 and assigns result back
value ^= 5; // also bitwise XORs 5 and assigns result back
// |=
value | 5; // bitwise ORs 5
value = value | 5; // bitwise ORs 5 and assigns result back
value |= 5; // also bitwise ORs 5 and assigns result back
```