Operator Declarations by Example - Swift Programming Language

An operator is a special symbol or phrase that you use to check, change, or combine values. For example, the addition operator (+) adds two numbers, as in let i = 1 + 2.

Swift supports most standard C operators and improves several capabilities to eliminate common coding errors. Like, the assignment operator (=) doesn’t return a value, to prevent it from being mistakenly used when the equal to operator (==) is intended. The tables below list the operators declared in Swift.

Table 1 - Prefix operators

Operator Description
! Logical NOT
~ Bitwise NOT
+ Unary plus
- Unary minus
..< Half-open range
... Closed range

Table 2 - Postfix operators

Operator Description
... Closed Range

Table 3 - Infix operators

The infix operators are grouped below by precedence group in decreasing order of precedence.

Operator Description Associativity Precedence group
<< Bitwise left shift None BitwiseShiftPrecedence
>> Bitwise right shift None BitwiseShiftPrecedence
+ Add Left associative AdditionPrecedence
- Subtract Left associative AdditionPrecedence
* Multiply Left associative MultiplicationPrecedence
/ Divide Left associative MultiplicationPrecedence
% Remainder Left associative MultiplicationPrecedence
&+ Add with overflow Left associative AdditionPrecedence
&- Subtract with overflow Left associative AdditionPrecedence
&* Multiply with overflow Left associative MultiplicationPrecedence
& Bitwise AND Left associative MultiplicationPrecedence
| Bitwise OR Left associative AdditionPrecedence
^ Bitwise XOR Left associative AdditionPrecedence
..< Half-open range None RangeFormationPrecedence
... Closed range None RangeFormationPrecedence
is Type check Left associative CastingPrecedence
as, as?, and as! Type cast Left associative CastingPrecedence
?? Nil coalescing Right associative NilCoalescingPrecedence
?: Ternary conditional Right associative TernaryPrecedence
< Less than None ComparisonPrecedence
<= Less than or equal None ComparisonPrecedence
> Greater than None ComparisonPrecedence
>= Greater than or equal None ComparisonPrecedence
= = Equal None ComparisonPrecedence
!= Not equal None ComparisonPrecedence
= = = Identical None ComparisonPrecedence
!= = = Not identical None ComparisonPrecedence
~= Pattern match None ComparisonPrecedence
&& Logical AND Left associative LogicalConjunctionPrecedence
|| Logical OR Left associative LogicalConjunctionPrecedence
= Assign Right associative AssignmentPrecedence
*= Multiply and assign Right associative AssignmentPrecedence
/= Divide and assign Right associative AssignmentPrecedence
%= Remainder and assign Right associative AssignmentPrecedence
+= Add and assign Right associative AssignmentPrecedence
-= Subtract and assign Right associative AssignmentPrecedence
<<= Left bit shift and assign Right associative AssignmentPrecedence
>>= Right bit shift and assign Right associative AssignmentPrecedence
&= Bitwise AND and assign Right associative AssignmentPrecedence
|= Bitwise OR and assign Right associative AssignmentPrecedence
^= Bitwise OR and assign Right associative AssignmentPrecedence

1. Prefix operators

1.1 Logical NOT (!)

The logical NOT operator (!) inverts a Boolean value so that true becomes false, and false becomes true.

let allowedEntry = false  
if !allowedEntry {  
    print("ACCESS DENIED")
}

//prints "ACCESS DENIED"

1.2 Bitwise NOT (~)

The bitwise NOT operator (~) inverts all bits in a number.

let initialBits: UInt8 = 0b00001111  
let invertedBits = ~initialBits  // equals 11110000  
print(invertedBits)

//prints "240"

1.3 Unary plus (+)

The unary plus operator (+) simply returns the value it operates on, without any change.

let minusSix = -6  
let alsoMinusSix = +minusSix  
print(alsoMinusSix)

//prints "-6"

Although the unary plus operator doesn’t actually do anything, we can use it to provide symmetry in your code for positive numbers when also using the unary minus operator for negative numbers.

1.4 Unary minus (-)

The sign of a numeric value can be toggled using a prefixed -, known as the unary minus operator.

let three = 3  
let minusThree = -three  
print(minusThree)  
//prints "-3"

let plusThree = -minusThree  
print(plusThree)  
//prints "3"

1.5 Half-open range (..<)

The half-open range operator (a ..< b) defines a range that runs from a to b, but doesn’t include b. The half-open range operator also has a one-sided form that’s written with only its final value.

let names = ["Anna", "Alex", "Brian", "Jack"]  
for name in names[..<2] {  
    print(name)
}
/* prints -
Anna  
Alex */  

1.6 Closed range (...)

The closed range operator (a...b) defines a range that runs from a to b, and includes the values a and b. The value of a must not be greater than b. The closed range operator has an alternative form for ranges that continue as far as possible in one direction

for name in names[...2] {  
    print(name)
}
/* prints -
Anna  
Alex  
Brian  
*/

2. Postfix operators

2.1 Closed range (...)

For definition refer 1.6 Closed range

for name in names[2...] {  
    print(name)
}
/* prints -
Brian  
Jack  
*/

3. Infix operators

3.1 Bitwise left shift (<<)

The bitwise left shift operator (<<) move all bits in a number to the left by a certain number of places, according to the rules defined below.

  • Bitwise left shifts have the effect of multiplying an integer by a factor of two.
let shiftBits: UInt8 = 4   // 00000100 in binary  
shiftBits << 1             // 00001000  
shiftBits << 2             // 00010000  
shiftBits << 5             // 10000000  
shiftBits << 6             // 00000000  

3.2 Bitwise right shift (>>)

The bitwise right shift operator (>>) move all bits in a number to the right by a certain number of places, according to the rules defined below.

  • Bitwise right shifts have the effect of dividing an integer by a factor of two.
let shiftBits: UInt8 = 4   // 00000100 in binary  
shiftBits >> 1             // 00000010  
shiftBits >> 2             // 00000001  
shiftBits >> 3             // 00000000  

3.3 Add (+)

Add operator computes addition.

let num1 = 10  
let num2 = 2  
let addition = num1 + num2  
print(addition)

//prints "12"

3.4 Subtract (-)

Subtract operator computes subtraction.

let num1 = 10  
let num2 = 2  
let subtraction = num1 - num2  
print(subtraction)

//prints "8"

3.5 Multiply (*)

Multiply operator computes multiplication.

let num1 = 10  
let num2 = 2  
let multiplication = num1 * num2  
print(multiplication)

//prints "20"

3.6 Divide (/)

Divide operator computes division.

let num1 = 10  
let num2 = 2  
let division = num1 / num2  
print(division)

//prints "5"

3.7 Remainder (%)

Remainder operator computes remainder after division.

let num1 = 10  
let num2 = 2  
let remainder = num1 % num2  
print(remainder)

//prints "0"

3.8 Add with overflow (&+)

Overflow Add operator computes addition. Addition result can overflow in both the positive and negative direction.

Arithmetic operators (+, -, *, /, % and so forth) detect and disallow value overflow, to avoid unexpected results when working with numbers that become larger or smaller than the allowed value range of the type that stores them.

For example, the Int16 integer type can hold any signed integer between -32768 and 32767. Trying to set an Int16 constant or variable to a number outside of this range causes an error:

var potentialOverflow = Int16.max  
potentialOverflow = potentialOverflow + 1 // this causes an error  

Here’s an example of what happens when an Int16 is allowed to overflow, using the overflow add operator (&+):

var int16Overflow = Int16.max  
int16Overflow = int16Overflow &+ 1  
print(int16Overflow)

//prints "-32768"

3.9 Subtract with overflow (&-)

Overflow Subtract operator computes subtraction. Subtraction result can overflow in both the positive and negative direction. Here’s an example of what happens when an Int16 is allowed to overflow, using the overflow subtract operator (&-):

var int16Overflow = Int16.min  // -32768  
int16Overflow = int16Overflow &- 1  
print(int16Overflow)

//prints "32767"

3.10 Multiply with overflow (&*)

Overflow Multiply operator computes multiplication. Multiplication result can overflow in both the positive and negative direction. Here’s an example of what happens when an Int16 is allowed to overflow, using the overflow multiply operator (&*):

var int16Overflow = Int16.max  
int16Overflow = int16Overflow &* 2  
print(int16Overflow)

//prints "-2"

3.11 Bitwise AND (&)

The bitwise AND operator (&) combines the bits of two numbers. It returns a new number whose bits are set to 1 only if the bits were equal to 1 in both input numbers:

let firstSixBits: UInt8 = 0b11111100  
let lastSixBits: UInt8  = 0b00111111  
let middleFourBits = firstSixBits & lastSixBits  
print(middleFourBits)

//prints "60"
//60 = 00111100 in binary

3.12 Bitwise OR (|)

The bitwise OR operator (|) compares the bits of two numbers. The operator returns a new number whose bits are set to 1 if the bits are equal to 1 in either input number:

let someBits: UInt8 = 0b10110010  
let moreBits: UInt8 = 0b01011110  
let combinedbits = someBits | moreBits  
print(combinedbits)

//prints "254"
//254 = 11111110 in binary

3.13 Bitwise XOR (^)

The bitwise XOR operator, or “exclusive OR operator” (^), compares the bits of two numbers. The operator returns a new number whose bits are set to 1 where the input bits are different and are set to 0 where the input bits are the same:

let firstBits: UInt8 = 0b00010100  
let otherBits: UInt8 = 0b00000101  
let outputBits = firstBits ^ otherBits  
print(outputBits) 

//prints "17"
//17 = 00010001

3.14 Half-open range (..<)

For definition refer 1.5 Half-open range

Half-open ranges are particularly useful when you work with zero-based lists such as arrays, where it’s useful to count up to (but not including) the length of the list

let names = ["Anna", "Alex", "Brian", "Jack"]  
let count = names.count  
for i in 0..<count {  
    print("Person \(i + 1) is called \(names[i])")
}

//prints -
/*
Person 1 is called Anna  
Person 2 is called Alex  
Person 3 is called Brian  
Person 4 is called Jack  
*/

3.15 Closed range (...)

For definition refer 1.6 Closed range

The closed range operator is useful when iterating over a range in which you want all of the values to be used, such as with a for-in loop:

for index in 1...5 {  
    print("\(index) times 5 is \(index * 5)")
}

//prints-
/*
1 times 5 is 5  
2 times 5 is 10  
3 times 5 is 15  
4 times 5 is 20  
5 times 5 is 25  
*/

3.16 Type check (is)

We use type check operator (is) to check whether an instance is of a certain subclass type. The type check operator returns true if the instance is of that subclass type and false if it is not.

let number = 1  
let isNumberInt = number is Int  
let isNumberFloat = number is Float  
print(isNumberInt) //prints "true"  
print(isNumberFloat) //prints "false"  

3.17 Type cast (as, as?, and as!)

A constant or variable of a certain class type may actually refer to an instance of a subclass behind the scenes. Where you believe this is the case, you can try to downcast to the subclass type with a type cast operator (as? or as!).

Because downcasting can fail, the type cast operator comes in two different forms. The conditional form, as?, returns an optional value of the type you are trying to downcast to. The forced form, as!, attempts the downcast and force-unwraps the result as a single compound action.

as? - Use the conditional form of the type cast operator (as?) when you are not sure if the downcast will succeed. This form of the operator will always return an optional value, and the value will be nil if the downcast was not possible. This enables you to check for a successful downcast.

let randomObjectsArray: [Any] = [1, 1.2, "Hello", true, [1, 2, 3], "World!"]  
for object in randomObjectsArray {  
    if let stringObject = object as? String {
        print(stringObject)
    }
}

as! - Use the forced form of the type cast operator (as!) only when you are sure that the downcast will always succeed. This form of the operator will trigger a runtime error if you try to downcast to an incorrect class type.

let randomIntArray: [Any] = [1, 2, 3, 4, 5]  
for object in randomIntArray {  
    let intObject = object as! Int
    print(intObject)
}

3.18 Nil coalescing (??)

The nil-coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil. The expression a is always of an optional type. The expression b must match the type that is stored inside a.

let defaultColorName = "red"  
var userDefinedColorName: String?   // defaults to nil

var colorNameToUse = userDefinedColorName ?? defaultColorName  
print(colorNameToUse)

//prints "red"
// userDefinedColorName is nil, so colorNameToUse is set to the default of "red"

userDefinedColorName = "green"  
colorNameToUse = userDefinedColorName ?? defaultColorName  
print(colorNameToUse)

//prints "green"
// Now userDefinedColorName is "green", so colorNameToUse is set to the value of userDefinedColorName of "green"

3.19 Ternary conditional (?:)

The ternary conditional operator is a special operator with three parts, which takes the form question ? answer1 : answer2. It’s a shortcut for evaluating one of two expressions based on whether question is true or false. If question is true, it evaluates answer1 and returns its value; otherwise, it evaluates answer2 and returns its value.

let contentHeight = 40  
let hasHeader = true  
let rowHeight = contentHeight + (hasHeader ? 50 : 20)  
print(rowHeight)

//prints "90"

3.20 Less than (<)

Less than operator checks if the value of left operand is less than the value of right operand. If yes, then the condition becomes true.

let isOneLessThanTwo = 1 < 2  
print(isOneLessThanTwo)

//prints "true"

3.21 Less than or equal (<=)

Less than or equal operator checks if the value of left operand is less than or equal to the value of right operand. If yes, then the condition becomes true.

let isOneLessThanOrEqualToOne = 1 <= 1  
print(isOneLessThanOrEqualToOne)

//print "true"

3.22 Greater than (>)

Greater than operator checks if the value of left operand is greater than the value of right operand. If yes, then the condition becomes true.

let isOneGreaterThanTwo = (1 > 2)  
print(isOneGreaterThanTwo)

//print "false"

3.23 Greater than or equal (>=)

Greater than or equal operator checks if the value of left operand is greater than or equal to the value of right operand. If yes, then the condition becomes true.

let isOneGreaterThanOrEqualToTwo = (1 >= 2)  
print(isOneGreaterThanOrEqualToTwo)

//prints "false"

3.24 Equal (= =)

Equal operator checks if the values of two operands are equal or not. If yes, then the condition becomes true.

let isOneEqualToTwo = (1 == 2)  
print(isOneEqualToTwo)

//prints "false"

3.25 Not equal (!=)

Not equal checks if the values of two operands are equal or not. If the values are not equal, then the condition becomes true.

let isOneNotEqualToTwo = (1 != 2)  
print(isOneNotEqualToTwo)

//prints "true"

3.26 Identical (= = =)

Identical operator use to test whether two object references both refer to the same object instance.

let object1 = NSObject()  
let object2 = NSObject()  
let object3 = object1  
let object1IsIdenticalToObject3 = (object1 === object3)  
print(object1IsIdenticalToObject3)  

3.27 Not identical (!==)

Not identical operator use to test whether two object references both do not refer to the same object instance.

let object1IsNotIdebticalToObject2 = (object1 !== object2)  
print(object1IsNotIdebticalToObject2)  

3.28 Pattern match (~=)

Pattern match operator use to pattern matching in a case statement. We can overload the ~= operator to provide custom expression matching behaviour. Here is a simple example of defining a custom one and using it:

struct Person {  
    let name : String
}

// Function that should return true if value matches against pattern
func ~=(pattern: String, value: Person) -> Bool {  
    return value.name == pattern
}

let p = Person(name: "Vineet")  
switch p {  
case "Vineet":  
    print("Hey it's me!")
default:  
    print("Not me")
}
// prints  "Hey it's me!"

if case "Vineet" = p {  
    print("It's still me!")
}
// prints "It's still me!"

3.29 Logical AND (&&)

The logical AND operator (a && b) creates logical expressions where both values must be true for the overall expression to also be true.

If either value is false, the overall expression will also be false. In fact, if the first value is false, the second value won’t even be evaluated, because it can’t possibly make the overall expression equate to true. This is known as short-circuit evaluation.

let enteredDoorCode = true  
let passedRetinaScan = false  
if enteredDoorCode && passedRetinaScan {  
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}

//Prints "ACCESS DENIED"

3.30 Logical OR (||)

The logical OR operator (a || b) use to create logical expressions in which only one of the two values has to be true for the overall expression to be true.

Like the Logical AND operator above, the Logical OR operator uses short-circuit evaluation to consider its expressions. If the left side of a Logical OR expression is true, the right side is not evaluated, because it can’t change the outcome of the overall expression.

let hasDoorKey = false  
let knowsOverridePassword = true  
if hasDoorKey || knowsOverridePassword {  
    print("Welcome!")
} else {
    print("ACCESS DENIED")
}
// Prints "Welcome!"

3.31 Assign (=)

Simple assignment operator. Assigns values from right side operands to left side operand.

let b = 5  
var a = 10  
a = b  
print(a)

//prints 5

3.32 Multiply and assign (*=)

Multiply and assignment operator. It multiplies the right operand with the left operand and assigns the result to the left operand.

let b = 5  
var a = 10  
a *= b  
print(a)

//prints 50

3.33 Divide and assign (/=)

Divide and assignment operator. It divides the left operand with the right operand and assigns the result to the left operand.

let b = 5  
var a = 10  
a /= b  
print(a)

//prints 2

3.34 Remainder and assign (%=)

Modulus and assignment operator. It takes modulus using two operands and assigns the result to the left operand.

let b = 5  
var a = 10  
a %= b  
print(a)

//prints 0

3.35 Add and assign (+=)

Add and assignment operator. It adds the right operand to the left operand and assign the result to the left operand.

let b = 5  
var a = 10  
a += b  
print(a)

//prints 15

3.36 Subtract and assign (-=)

Subtract and assignment operator. It subtracts the right operand from the left operand and assigns the result to the left operand.

let b = 5  
var a = 10  
a -= b  
print(a)

//prints 5

3.37 Left bit shift and assign (<<=)

Left shift and assignment operator.

var shiftBitsAndAssign: UInt8 = 4   //00000100 in binary  
shiftBitsAndAssign <<= 1             //00001000  
shiftBitsAndAssign <<= 2             //00100000  

3.38 Right bit shift and assign (>>=)

Right shift and assignment operator.

shiftBitsAndAssign >>= 1             //00010000  
shiftBitsAndAssign >>= 2             //00000100  

3.39 Bitwise AND and assign (&=)

Bitwise AND assignment operator.

var num1Bits: UInt8 = 0b11111100  
let num2Bits: UInt8  = 0b00111111  
num1Bits &= num2Bits  
print(num1Bits)

//prints "60"
//60 = 00111100 in binary

3.40 Bitwise OR and assign (|=)

Bitwise exclusive OR and assignment operator.

var num1Bits: UInt8 = 0b11111100  
let num2Bits: UInt8  = 0b00111111  
num1Bits &= num2Bits  
print(num1Bits)

//prints "255"
//255 = 11111111 in binary

3.41 Bitwise OR and assign (^=)

Bitwise inclusive OR and assignment operator.

var num1Bits: UInt8 = 0b11111100  
let num2Bits: UInt8  = 0b00111111  
num1Bits &= num2Bits  
print(num1Bits)

//prints "195"
//195 = 11000011 in binary

You can download the swift playground of all above examples from Here




Related Article