Basics
Unary, Binary, Ternary Operators
-
Unary – Operates on single operand
!true
-
Binary – Operates on a pair of operands
10 + 20
-
Ternary – Operates on 3 operands
count > 10 ? print("More") : print("Less") // ?: is a single ternary operator
Prefix, Infix, Postfix Operators
-
Prefix – operator placed before the operand
-10
-
Infix – operator placed between the operands
10 + 20
-
Postfix – operator placed after the operand
employeeCount++
Note: The operator ++ has been deprecated in Swift. At present there are
no postfix operators in Swift by default. However you may define
custom postfix operators including ++ if needed.
Operator Precedence
It is the evaluation priority of operators in an expression when mixed with operators of different precedence groups. This is determined by the relative priority of the precedence groups to which these operators belong.
2 + 3 * 4 // Result = 14 because it is evaluated as 2 + (3 * 4)
// + belongs to AdditionPrecedence group
// * belongs to MultiplicationPrecedence group
// AdditionPrecedence has lesser priority than MultiplicationPrecedence
Swift has many predefined precedence groups like AdditionPrecedence, MultiplicationPrecedence, ComparisonPrecedence etc.
Operator Associativity
It is the evaluation direction of operators in an expression when mixed with other operators in the same precedence group. This is determined by the associativity property of the precedence group to which these operators belong.
5 % 3 * 2 // Result = 4 because it is evaluated as (5 % 3) * 2
// % and * belong to MultiplicationPrecedence group which has
// left associativity. Hence the expression is evaluated from
// left to right.
In Swift the associativity of a precedence group can be left, right or none.
Built-In Operators
Arithmetic Operators
+ // Addition
- // Subtraction
* // Multiplication
/ // Division
Bitwise Operators
These operate on the binary content of the value or variable
~ // Bitwise NOT Eg: Result = ~InputVar
& // Bitwise AND Eg: Result = FirstVar & SecondVar
| // Bitwise OR Eg: Result = FirstVar | SecondVar
^ // Bitwise XOR Eg: Result = FirstVar ^ SecondVar
<< // Bitwise Left Shift Eg: Result = InputVar << 4
>> // Bitwise Right Shift Eg: Result = InputVar >> 5
Note:
* Left Shift and Right Shift of unsigned numbers discard the moved out bits and bring
in zeros at the other end. This is called logical shift.
* Left Shift of signed number works the same as that of unsigned number. Even the sign
bit is moved out and replaced by the shifted data bits. For example 10001000 becomes
00100000 after a left shift by 2 positions.
* Right Shift of signed number however retains the sign bit as such, in addition to
copying it to the most significant data bit with each shift. This is called an
arithmetic shift. For example 10001000 becomes 11110001 after a right shift by 3
positions.
Assignment Operator
Compound Assignment Operators
They combine assignment with another operation
+= // Add and Assign Eg: count += 1
-= // Subtract and Assign Eg: count -= 1
*= // Multiply and Assign Eg: count *= 2
/= // Divide and Assign Eg: count /= 2
%= // Remainder and Assign Eg: count %= 2
&= // Binary AND and Assign Eg: value &= 1
|= // Binary OR and Assign Eg: value |= 1
^= // Binary XOR and Assign Eg: value ^= 1
<<= // Left Shift and Assign Eg: value <<= 5
>>= // Right Shift and Assign Eg: value >>= 3
Overflow Operators
By default Swift throws error when the inserted/updated value of a constant/variable is beyond the range of values the respective type supports.
var sum: UInt8 = 0 // set sum to the minimum value supported by UInt8
sum = sum - 1 // throws error
var count: Int8 = 127 // set to the maximum value supported by Int8
count = count + 1 // throws error
However there are situations where the developer would prefer an overflow instead of error. For this Swift supports the following overflow operators.
&+ // Overflow addition
&- // Overflow subtraction
&* // Overflow multiplication
Basically, these operators cause the value to wrap around (the other end of the range). In the above example,
sum = sum &- 1 // sum now becomes 255
count = count &+ 1 // count now becomes -128
Custom Operators
Operator Methods
An operator method is a static method, defined inside a type definition/extension, with the operator symbol as the method name, in order for the operator to accept values of that type as operands. The body of the operator method should define the appropriate behavior for the operation on the type. Operator methods are used to support existing operators on a type that doesn’t support them yet (operator overloading) as well as to define completely new operators.
struct Score {
var physicsScore: Double = 0
var mathsScore: Double = 0
// Following is the operator method which defines overloaded behavior for +
// It is defined as a binary infix operator
static func + (left: Score, right: Score) -> Score {
return Score(physicsScore: left.physicsScore + right.physicsScore,
mathsScore: left.mathsScore + right.mathsScore)
}
// Following is the operator method which defines overloaded behavior for -
// It is defined as a unary prefix operator
static prefix func - (score: Score) -> Score {
return Score(physicsScore: -score.physicsScore, mathsScore: -score.mathsScore)
}
}
var firstSemScore = Score(physicsScore: 80, mathsScore: 85)
var secondSemScore = Score(physicsScore: 90, mathsScore: 95)
var totalScore = firstSemScore + secondSemScore // + is a binary infix operator
totalScore = -totalScore // - is a unary prefix operator
In order to overload a compound assignment operator, implement a binary infix method with the left parameter marked as inout.
struct Score {
var physicsScore: Double = 0
var mathsScore: Double = 0
// Overloaded method. Left parameter is inout and is assigned the result inside
// the method. Also note that the method need not return anything.
static func += (left: inout Score, right: Score) {
left = Score(physicsScore: left.physicsScore + right.physicsScore,
mathsScore: left.mathsScore + right.mathsScore)
}
}
var totalScore: Score = Score(physicsScore: 80, mathsScore: 85)
totalScore += Score(physicsScore: 90, mathsScore: 95)
Creating Custom Operators
Swift allows us to define custom operators as well. This involves a global declaration of the new operator and then defining the operator method within necessary structs, classes etc.
The global declaration syntax is different for different fixities (prefix, infix, postfix). Prefix and Postfix operators are non-associative and do not belong to any precedence group.
prefix operator OperatorSymbol
Eg: prefix operator +++
postfix operator OperatorSymbol
Eg: postfix operator +++
infix operator OperatorSymbol: PrecedenceGroup
Eg: infix operator +++ : AdditionPrecedence
Example
infix operator +++ : AdditionPrecedence
struct Score {
var physicsScore: Double = 0
var mathsScore: Double = 0
static func +++ (left: Score, right: Score) -> Score {
return Score(physicsScore: left.physicsScore + right.physicsScore + 100,
mathsScore: left.mathsScore + right.mathsScore + 100)
}
}
var firstSemScore = Score(physicsScore: 80, mathsScore: 85)
var secondSemScore = Score(physicsScore: 90, mathsScore: 95)
var totalScore = firstSemScore +++ secondSemScore
Note: Please refer to Apple documentation for the set of symbols that you can use to define a new operator.
Creating Custom Precedence Groups
A precedence group is declared as follows
precedencegroup precedenceGroupName {
higherThan : lower group names // Specify relation to any lower groups
lowerThan : higher group names // Specify relation to any higher groups
associativity : associativity // Specify the associativity (left, right, none)
assignment : assignment flag // Specify precedence while optional chaining
}
Note: The assignment flag decides the precedence of the operators of this group when used in an expression with optional chaining. When it is set to true, these operators follow the same grouping rules as the assignment operator. When set to false, they follow the optional chaining rules as those operators which do not perform assignment.
Example
precedencegroup myOperatorsPrecedence {
higherThan : AdditionPrecedence, ComparisonPrecedence
lowerThan : MultiplicationPrecedence
associativity : left
assignment : false
}