# Solidity Operators and ‘Delete’ Keyword

Throughout this article, we’ll take a dive into the topics of operators, specifically the ternary operator, compound and increment/decrement operators, and the `delete` keyword.

We’ll conclude the article with a table overviewing the operators in Solidity.

It’s part of our long-standing tradition to make this (and other) articles a faithful companion or a supplement to the official Solidity documentation.

## Solidity Operators

Operators can be coarsely divided into two categories:

• arithmetic and
• bit operators.

We can use both of these operators even when the operands don’t work with the same data types, e.g. `y = x + z`, even if `x` is of `uint8` type and `z` is of `int32` type.

When such a case occurs, there’s a simple set of rules used in determining the type used for the operation computation, as well as the final type of the computation result. This set of rules is particularly crucial when dealing with overflows.

These rules are:

1. If there’s a possibility of converting the right operand type to the left operand type, use the left operand type;
2. If there’s a possibility of converting the left operand type to the right operand type, use the right operand type;
3. in any other case, disallow the operation.

When one of the operands is a literal number, the mechanism will first convert it to its “mobile type”, i.e. the smallest (most compact) type that can hold the value (unsigned types of the same bit-width are treated as “smaller” than the signed types).

In case both operands are literal numbers, the mechanism computes the operation with arbitrary precision.

Furthermore, the operator’s result type corresponds to the type the operation is performed in, with an exception for comparison operators, which always produce a result of type `bool`, e.g. if the operation is performed in `uint8`, the operator’s result type will be `uint8`.

Exceptions to the rule are the operators `**` (exponentiation), `<<` (left shift operator), and `>>` (right shift operator) because they use the type of the left operand as a base type for determining both the operation type and the result type.

### Ternary Operator

The ternary operator is an operator commonly present in popular programming languages in one form or the other and is expressed in Solidity with syntax:

`<expression> ? <trueExpression> : <falseExpression>`

The result of using the ternary operator depends on evaluating the `<expression>`, i.e. if the `<expression>` evaluates as true, the result follows from evaluating `<trueExpression>`, and if the `<expression>` evaluates as false, the result follows from evaluating `<falseExpression>`.

The ternary operator does not result in a rational number type, even when all of its operands are rational number literals. In fact, the types of the two operands determine the result type following the same set of rules, including conversion to their mobile types if needed, i.e. when one of the operands is a literal type.

One example showing the set of rules at work is `255 + (true ? 1 : 0)`, which will revert because of an arithmetic overflow.

Since `(true ? 1 : 0)` is of `uint8` type, and following rule 1, the left operand is also of `uint8` type, `255 + 1 = 256`. The `uint8` type can hold unsigned integers ranging from 0 up to `2**8 - 1`, i.e. 255, so 256 is an overflowed result.

Another example is of a literal expression `1.5 + 1.5`, which is valid because it’s a rational expression evaluated in unlimited, i.e. arbitrary precision.

However, `1.5 + (true ? 1.5 : 2.5)` is not a valid expression, because as mentioned above, the result of the ternary operator doesn’t have a rational number type.

In other words, the ternary operator result would have to be converted to the only numeric type currently available, i.e. (unsigned) integer, while Solidity doesn’t currently support that kind of conversion.

### Compound and Increment/Decrement Operators

When looking at an assignment expression, we can identify two important parts: the left side and the right side.

👉 The commonly used term for the assignable left side, i.e. a variable, an object, or some other type of a value container is `Lvalue`, and for the right side is `Rvalue`.

Let’s assume the name `lv` represents an `Lvalue`: then `lv += e` is a synonym for `lv = lv + e`.

Operators` -=, *=, /=, %=, |=, &=, ^=, <<=` and `>>=` are interpreted in the same way. All these operators are known as compound operators.

📒 Note: we should make a difference between this kind of expression in mathematics, where it represents an equation, and in Solidity and the majority of other programming languages based on object-oriented, procedural, or declarative paradigms, it represents an assignment.

Post-increment and post-decrement operators `lv++` and `lv--` correspond to `lv += 1` and `lv -= 1`.

The prefix post- signifies that if a post-incremented or post-decremented variable `lv` is an `Rvalue`, i.e. it’s assigned to a variable `var`, the variable `var` will first get the current value of `lv`, and after that (hence post-) `lv` will change its value by 1.

Corresponding pre-increment and pre-decrement operators `++lv` and `--lv` will first (hence pre-) change the value of `lv` by 1, and only then assign the changed value to `var`.

## delete Keyword

Maybe not so frequently mentioned as some other constructs, the `delete` keyword is very useful.

Let’s choose a name for an unspecified type, e.g. `var`, and take a look at how delete operates on it.

`delete var` assigns the default value for the type to `var`.

If the type is an integer, value 0 is assigned to `var`.

If the type is a dynamic array, delete will assign 0 to its member property length; for a static array, it will set all elements to their default value.

`delete var[x]` will delete the item of index `x` and leave all other elements and the array length untouched, i.e. it leaves a gap in the array.

🛑 Warning: If we know our code design will require removing some items, the mapping data structure is recommended.

If `var` is of a `struct` type, it will assign a struct with all struct members reset to their default values. Generally speaking, `delete` behaves very similarly to declaring `var` without an assignment, but with an important warning.

🛑 Warning: “delete has no effect on mappings (as the keys of mappings may be arbitrary and are generally unknown). So if you delete a struct, it will reset all members that are not mappings and also recurse into the members unless they are mappings. However, individual keys and what they map to can be deleted: If var is a mapping, then delete var[x] will delete the value stored at x”. (docs)

Finally, we can conclude that the behavior of `delete var` corresponds to an assignment to `var`, because it stores a new object in `var`.

We can notice this behavior directly when `var` is a reference variable, because `delete var` will reset `var`, and not the value `var` previously referred to.

The following example nicely illustrates and confirms what we learned.

```// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;

contract DeleteExample {
uint data;
uint[] dataArray;

function f() public {
uint x = data;
delete x; // sets x to 0, does not affect data
delete data; // sets data to 0, does not affect x
uint[] storage y = dataArray;
delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also
// y is affected which is an alias to the storage object
// On the other hand: "delete y" is not valid, as assignments to local variables
// referencing storage objects can only be made from existing storage objects.
assert(y.length == 0);
}
}
```

## Order of Precedence of Operators

So far, we’ve seen many different operators in Solidity, and to make it practical, let’s list them in a table showing the order of operator precedence in order of evaluation.

📒 Note: order of operator precedence can be modified by using parentheses.

## Conclusion

In this article, we learned about operators, specifically ternary operators, compound, and increment/decrement operators. We also discussed what the `delete` keyword does with popular variable types.

• First, we divided the operators into two broad categories: arithmetic and bit operators. Then we learned about rules for determining the operation computation type and proceeded into details of the operand and result type determination.
• Second, we discussed the ternary operator mechanics and its specifics through theory and a couple of examples.
• Third, we sneaked on compound and increment/decrement operators and found out what they do
• Fourth, we made a short analysis of the `delete` keyword and took a look at how it operates with several types, particularly complex types.
• Fifth, we took a look at a table of operators in Solidity.

## What’s Next?

This tutorial is part of our extended Solidity documentation with videos and more accessible examples and explanations. You can navigate the series here (all links open in a new tab):