Dart Operators Precedence and Associativity
Precedence of operators determines the order in which the operators are evaluated if they are grouped together in a sentence. If two operators share an operand then the one with the higher precedence is executed first.
Program
Consider the following code in Dart that uses two Arithmetic Operators viz multiply (*) and add (+), and an assignment operator viz. equals to (=).
void main( )
{
int a = 5, b = 6, c = 7, res1 = 0, res2 = 0 ;
res1 = a + b * c ;
// result of first expression
print( res1 ) ;
res2 = a * b + c ;
// result of second expression
print( res2 ) ;
}
Output:
47
37
Let us understand how the answers to these two results differ. In the first expression res1 = a + b * c with a = 5, b = 6, and c = 7.
Multiplication is performed first because it has higher precedence than the addition operator.
Therefore, the answer evaluated to 47.
res1 = a + b * c = 5 + 6 * 7
= 5 + 42
= 47
Similarly in case of second expression,
Multiplication is performed first followed by addition
res2 = a * b + c = 5 * 6 + 7
= 30 + 7
= 37
Since the assignment operator has the least precedence out of these three, it is used at the last after we have evaluated the expression at the right. And then using assignment operator the value evaluated is assigned to the variable on the left.
Sometimes, the operators with same precedence are used in an expression together. In that case we need a rule that defines the order in which they should be performed and that is given by Associativity of the operators. It determines the direction in which an expression is evaluated. It can be either Left to Right or Right to Left.
Program
Consider the following code in Dart that uses Multiplicative operators : multiply (*) and divide (/), Additive Operators : add (+) and subtract (-) and assignment operator : equals to (=)
void main( )
{
int a = 12, b = 6, c = 16, d = 8;
var res1, res2, res3, res4;
res1 = a - b + c * d;
// result of first expression
print( res1 ) ;
res2 = a / b * c + d ;
// result of second expression
print( res2 ) ;
res3 = a * b / c - d ;
// result of third expression
print( res3 ) ;
res4 = a + b - c / d ;
// result of fourth expression
print( res4 ) ;
}
Output:
134
40
-3.5
16
PRECEDENCE AND ASSOCIATIVITY TABLE
Let’s have a look at the table that defines the precedence and associativity of each operator in Dart.
LEVEL | CATEGORY | OPERATOR | ASSOCIATIVITY |
16 | Unary Postfix | expr. expr ?. expr ++ expr -- expr1 [ expr2 ] expr( ) | |
15 | Unary Prefix | - expr ! expr ++ expr -- expr ~ expr await expr | |
14 | Multiplicative | * / ~ / % | Left – to - right |
13 | Additive | + - | Left - to - right |
12 | Shift | < < > > > > > > | Left – to - right |
11 | Bitwise AND | & | Left - to - right |
10 | Bitwise XOR | ^ | Left – to - right |
9 | Bitwise OR Postrix | | | Left – to - right |
8 | Relation and Test type | < > < = > = as is is! | |
7 | Equality | = = = ! | |
6 | Logical AND | && | Left – to - right |
5 | Logical OR | | | | Left - to - right |
4 | If null | expr1 ?? expr2 | Left – to - right |
3 | Conditional | expr ? expr1 : expr2 | Right - to - left |
2 | Cascade | . . | Left – to - right |
1 | Assignment | = * = / = + = - = & = ^ = < * lt ; = >> = ?? = ~ / =. | = % = | Right - to - left |
Overriding Precedence
We are clear by now that the operators are executed in an expression as per their precedence. But what if we want them to be executed exactly in the sequence they are written in an expression?
For example
In an expression that contains multiplication operator (*) and addition operator (+), we know that multiplication will be done first. But in order to perform addition first, we can use round parenthesis with the operator and operands.
Consider the following code in Dart that explains the above point
void main( )
{
int a = 5, b = 6, c = 7;
var res1, res2, res3, res4 ;
res1 = a + b * c ;
// printing the result of first expression
print( res1 ) ;
res2 = a * b + c ;
// printing the result of second expression
print( res2 ) ;
res3 = ( a + b ) * c ;
// printing the result of third expression
print( res3 ) ;
res4 = ( a * b ) + c ;
// printing the result of fourth expression
print( res4 ) ;
}
Output:
47
37
77
37
Precedence Class
A particular row in the Dart expression precedence table is represented by an instance of the expression class. This allows programmers to determine when parentheses are required (by comparing precedence values), but ensures that the programmer does not depend on the particular integers used by the analyser to represent table rows, since it may be required to change these integers from time to time to accommodate new language features.
Constructors
- Precedence.forTokenType constructor = This constructor is used to construct the precedence of the unary or binary expression containing operators of a particular given ‘type’.
Implementation = Precedence.forTokenType ( TokenType type ) : this._( type.precedence ) ;
Properties
1. HashCode =
Returns the hash code for a numerical value, and it returns the same value for int and doubles when the value provided is the same.
Implementation =
@override
int get hashCode = > _index.hashCode ;
2. Runtime Type =
Represents the type of runtime an object has.
Implementation = external Type get runtimeType ;
Operators
1. Operator <
It checks whether the precedence represents a looser binding than other, and accordingly returns true or false.
Implementation = bool operator < ( Precedence other ) = > _index < other._index ;
2. Operator < =
It checks whether the precedence represents a looser, or equal binding than other, and accordingly returns true or false.
Implementation = bool operator < = ( Precedence other ) = > _index < = other._index ;
3. Operator = =
It returns true if and only if this object and the other are the same.
Implementation =
@override
bool operator = = ( Object other ) = >
other is Precedence && _index = = other._index ;
4. Operator >
It checks whether the precedence represents a tighter binding than other, and accordingly returns true or false.
Implementation = bool operator > ( Precedence other ) = > _index > other._index ;
5. Operator > =
It checks whether the precedence represents a tighter, or equal binding than other, and accordingly returns true or false.
Implementation = bool operator > = ( Precedence other ) = > _index > = other._index ;