Tuesday, April 3, 2018

Swift 4 Introduction Series 1.7 - Swift Operators

Swift Operators

Swift support most of the standard operator other programming language uses. In addition, Swift improves the safety while using these operators.  


All standard operators are classified into 3 types of operator. They are:
  • Unary Operator: Unary operator works with a single operand. It can be placed in front of an operand (prefix) or placed behind an operand (postfix). Examples of prefix unary operator are -variable1, -10 and !variable2. Example of postfix unary operator is variable3!   
  • Binary Operator: Binary operator works in between 2 operand. Examples of binary operator are a + b, c / d and e * f
  • Ternary Operator: Ternary operator works with 3 operand. There is only one ternary operator in Swift; it is the ternary conditional operator (a ? b : c)


In a statement 1 + 2, the plus sign is the operator and the numbers are operands.

Assignment Operator

The most common and basic operator is the assignment operator. The basic syntax is as follows:


<variable_name> = <value/expression_that_fits_to_the_datatype>


Example:
var sampleNumber1 = 0

sampleNumber1 = 256

let sampleNumber2 = 242

sampleNumber1 = sampleNumber2

print(sampleNumber2)




For tuples, we can assign multiple value to multiple variables/constant at once.


Example:
let (a, b, c) = (12, 2.78, "Test")
a
b
c




Assignment Operator Do Not Return Value

Unlike other programming language, Swift assignment operator does not return a number or boolean value.


In C programming, we can combine assignment statement with if such as if a = b {...}. In C programming, a = b will return true if the assignment is successful.


We cannot combine assignment and if statement in Swift because the assignment statement in Swift do not return anything. To compare an assigned value we must use comparison operator.


Arithmetic Operator

Similar to other programming language, we have the standard arithmetic operator as shown below:


  • Addition (+)
  • Subtraction (-)
  • Multiplication (*)
  • Division (/)


The abovementioned arithmetic operator are binary operator and it work between 2 operand as shown in the example below:


12+54

132 - 65

23*65

9823 / 3

// For division, please be aware of floating point data type
9823 / 3.0




Additional Note:
  • Please use floating point for division to get accurate result.
  • Please note that any number divide by zero will return error




As previously mentioned in the data type section, we do not have integer overflow in Swift. Swift will return error for any attempt of integer overflow.


Example:
let intMax = Int.max

// intMax is 9223372036854775807

//let test1 = intMax + 1
//Above statement will generate error remove the comment for testing




Remainder Operator

Remainder operator is denoted as %. This operator will return the remainder after a division is performed. For example 11 % 3 will return a remainder of 2 and 11 % 2 will give a remainder of 1. See example below.


Example
11 % 3

10 % 3

11 % 2




Rules of Remainder Operator

Swift use the following formula: a = (b * some multiplier) + remainder to derived the remainder. The sign of b is always ignore. Therefore, a % b and a % -b always give same answer. -a % b will give you negative number. Please also note that Swift remainder operator only work with integer and it doesn't work on floating point number.


Remainder Operator with Negative Number

The remainder operator also work with negative number. However the remainder will be negative only if the first operand (dividend) is negative. If the divisor is negative, the remainder will still be positive.


Example:
11 % 3

-11 % 3

11 % -3

-11 % -3



Modulus and Remainder Operator

A lot of programmers confuse between modulus and remainder operator. Some programming languages uses % as modulus operator and some programming language uses % as remainder operator.


Modulus operator and remainder operator yield the same result when performing division with positive number. The difference between the two types of operator differs when dealing with negative number.


See example below:


The following is the remainder operation using Swift:




The following is the modulus operation in Python 2.7 (available in Mac OS)


As shown above, if both dividend and divisor is positive or negative; the operator return the same result.


However, if dividend or divisor is negative, the result is different.


We would like to check when divisor is positive; what will happen to the remainder if we move the dividend from positive number to negative number.


Example:


for i in -12...12 {
   
   print("\(i) % 3 is \(i % 3)")
}


The result is as follows


From the remainder operation, we know that once the dividend is negative, the remainder will be negative.




For modulus operation, whether the dividend is negative or positive, the remainder is always positive. In addition, the computation of mod is different from Swift when the dividend is negative. To derived -11 % 3, Python use the formula (-multiples x multiples) + modulus. In our example, the multiple is derived as -4 x 3 = -12. Therefore, -12 + modulus = -11 thus modulus is 1. Please note that modulus must be positive. we cannot use -9 and -2(modulus) to derived -11.

Please note that for C type of programming language, such as C, C#, Java, JavaScript and Swift; the implementation is the same. Programming language such as Python, Smalltalk, Perl, MATLAB, Haskell and Common LISP are using the other type of implementation.

Please also note that some programming language provides 2 difference kind of implementation. In Python, to implement the remainder operation similar to Swift or C, we need to use math.fmod.


The previous section is not a comprehensive examination of difference between remainder and modulus operation. This is just a reminder to programmer that there are differences between modulus and remainder when we use them to deal with negative number.


Remainder for Floating Point Number

To use remainder for floating point number we can use the function remainder(_,_) or truncatingRemainder(dividingBy:)


Both functions produce different result. See example below"


We will not examine this in detail.


Unary Minus Operator

We can convert a positive number to negative number using the unary minus operator (-). See example below:


Example:


let a = 13

let b = -a

let c = -b




Note: We use the unary minus operator to convert from positive number to negative number. We can also use the same operator to convert negative number to positive number as shown above.


Unary plus operator has no effect in Swift.


Application of Arithmetic Operator



Example:


let unitPrice = 25.5
let quantity = 12546
let deposit = 10034.80

let amount = unitPrice * Double(quantity)

let discount = amount * 0.05

let discountAmount = -discount

let payableAmount = amount + discountAmount




// Continuation from previous code
let salesTax = payableAmount * 0.07

let totalAmount = payableAmount + salesTax

let cashPayment = totalAmount - deposit

let totalUnitCost = totalAmount / 12546




Compound Assignment Operator



Compound assignment operator such as a += x is a short form of writing a = a + x. We have the following type of compound assignment operator:


  • Addition (+=) same as a = a + x
  • Subtraction (-=) same as a = a - x
  • Multiplication (*=) same as a = a * x
  • Division (/=) same as a = a / x
  • Remainder (%=) same as a = a % x


Example:


var a = 10

a -= 1

a *= 2

a /= 2

a += 2

a %= 2




Note:
Compound statement do not return value.
You cannot use the following


   let var551 = var54 += 5
or
   let var551 = (var54 += 5)


Example:


var 54 = 10
//let var551 = (var54 += 5) // Will generate error warning


Comparison Operator

Comparison operator compare numbers and return if the test is true. The following are the comparison operators:


  • Equal (==)
  • Not Equal (!=)
  • Greater than (>)
  • Less than (<)
  • Greater than OR Equal to (>=)
  • Less than OR Equal to (<=)


Each comparison return a boolean value.


Example:


10 == 10
20 == 21

123 != 934
123 != 123

12476 > 887
12476 > 12476
12476 > 12477

768 < 409098
409098 < 409098
409099 < 409098




Example 2:


1776 >= 1775
1776 >= 1776
1776 >= 1777

7172 <= 7173
7172 <= 7172
7172 <= 7171




We can also compare tuples against tuples. The comparison worked by comparing each element from left to right. For equal (==) comparison, the system will compare the leftmost element with first element on the right; if it is equal and the result is true then the system will proceed to compare the second element. If it is not equal, the system will return false after the first comparison and stop the comparing operation.


let originalTuples = ("a", 12, 2.78)

// Only true when all element is true
originalTuples == ("a",12,2.78)
originalTuples == ("A",12,2.78)




Similarly, for not equal operation (!=), the system will compare each element. If the result is false (Equal), the system will compare the next element. If the comparison result is true (Not Equal), the system will stop comparing.

let originalTuples = ("z", 10, 2.788)

// Only false when all element is false
originalTuples != ("c",12,98)
originalTuples != ("z",10,2.788)
originalTuples != ("a",10,2.78)
// previous statement 2.78 is != 2.788




We can use the greater or less than sign to compare tuples element. The system


let originalTuples = ("a", 14, 2.7888) // For string or character it compares the ranking in the Unicode table // b is greater than a originalTuples > ("b", 14, 77.8) // character "2" is smaller than "a", did not compare 55.8 vs 2.788 originalTuples > ("2", 14, 55.8) // Return the last result since first 2 element is equal originalTuples > ("a", 14, 0.8) // Return the last result since first 2 element is equal originalTuples > ("a", 14, 55.8) // Return the second result since first element is equal, ignore last element originalTuples > ("a", 56, 0.08) // Return the second result since first element is equal, ignore last element originalTuples > ("a", 3, 55.8)





Note:
Please note that we can compare character or string in addition of numbers. However, we cannot use greater than or less than sign for boolean variables. Using greater for less than sign for boolean variables will generate error. For Boolean variables, we can use equal or not equal comparison.


Example:
The following examples shows tuples comparison with Boolean variables


let someOriginalTuples = (true, false, 12)
someOriginalTuples == (false, false,12)
someOriginalTuples == (true, false, 12)




If we use Boolean variable with greater or less than sign, it will generate error.




Important Note:
The comparator operator is able to compare tuples with 6 element or less. If our tuples have 7 or more element, we must implement the comparison individually.


Example:
The following example shows the maximum number of element tuples can be used for comparison with comparison operator.


let someOriginalTuples3 = (1, 2, 3, 4, 5, 6)
someOriginalTuples3 > (0, 1, 2, 3, 4, 5)




Example:
The following example shows failed comparison if we are comparing 7 or more element in a  tuples.




To perform 7 element comparison, use the example below:


let someOriginalTuples4 = (1, 2, 3, 4, 5, 6, 7)
someOriginalTuples4.0 > 0
someOriginalTuples4.1 > 1
someOriginalTuples4.2 > 2
someOriginalTuples4.3 > 3
someOriginalTuples4.4 > 4
someOriginalTuples4.5 > 5
someOriginalTuples4.6 > 6




Ternary Conditional Operator

Ternary operator consist of 3 parts. The syntax is as follows:


<query>?<answer1>:<answer2>


The system will evaluate the query and if the expression evaluate to true, then the system will return the evaluated value of answer1. If the query is false, the system will return the evaluated value of answer2.


Ternary operator is the condensed version of the following code:


if query {
answer1
} else {
answer2
}


Example:


var result = ""
let student1 = 65

result = student1 > 50 ? "pass" : "fail"

print("Student 1 \(result)")






The ternary operator is similar to the code below:


var result = ""
let student1 = 65

if student1 > 50 {
  result = "pass"
} else {
   result = "fail"
}

print("Student 1 \(result)")




As ternary operator is hard to understand, so we are encourage to use it wisely and avoid combining multiple ternary operation into one compound statement


Nil-Coalescing Operator

Nil-coalescing operator (??) unwraps the value of an optional variable if it is not nil. If the optional variable is nil, it will default to the second provided value. The syntax is as follows:


<optional_variable> ?? <value_used_when_optionl_is_nil>
For example, let consider userDefineColor ?? defaultColor. The variable userDefineColor is an optional. If there is value in this variable then the system will unwrap the value in this variable. If on the other hand this variable is found to be nil, then the system will use the value defaultColor.


The whole construct can be form using the program below:


if userDefineColor != nil {
colorUsed = userDefineColor
} else {
colorUsed = defaultColor
}


Example:


let defaultColor = "red"
let userDefinedColor:String? = nil

let colorUsed = userDefinedColor ?? defaultColor

print("Color used is \(colorUsed).")


If our optional contains value, then the value will be unwrapped and utilized.


let defaultColor = "red"
let userDefinedColor:String? = "green"

let colorUsed = userDefinedColor ?? defaultColor

print("Color used is \(colorUsed).")





Range Operator

There are three types of range operator, the closed range operator, half-open range operator and one-sided range operator.


Closed Range Operator

Closed range operator is represented by (...). Closed range operator include the begin number and end number. To use closed range operator, please follow the syntax:


<begin_number>...<end_number>


Example:


1...10

let set1 = 1...16




We can use close range operator to define a range of index as shown in the example below:


for index in 1...10 {
    print("Item: \(index)")
}




Half-Open Range Operator

Half-open range operator is represented by (..<). It include the first number and the number less than the last number (last_number - 1). The syntax is as follows:


<begin_number>..<<last_number>


Example


for index in 1..<10 {
    print("Item:\(index)")
}




Half-range operator is useful when referencing arrays or any data index that starts from 0 and ends at total count less one.


Example:


let myArrays = [0,1,2,3,4,5,6,7,8,9]

let count = myArrays.count

for index in 0..<count {
    print("Number: \(index)")
}




Application of Range Operators

We can also use range operators as subscripts in an array. Listed below is an example using range operators with array.


let someArrayA = [1,2,3,4,5,6,7,8,9,10]
someArrayA[0]
someArrayA[9]
someArrayA.count
someArrayA.last

someArrayA[3...7]
someArrayA[3..<7]




We can also define range and use it in any other context besides subscripts:


// Define closed range
let someRange1 = 1...10
for index in someRange1 {
   print(index)
}
// Print 1 to 10

// Define half open range
let someRange2 = 1..<16
for index in someRange2 {
   print(index)
}
// Print 1 to 15





One-Sided Range Operator

One-sided range operator is range operator without a beginning or end number. It can be apply to any closed range operator or half-open range operator.

One-Sided Close Range Operator

One-sided close range operator can be written as


...5 or 1…


The interpretation of one-sided operator is as follows:
  • ...5 - tell the system to count from beginning of index (could be 0 or 1) to 5 inclusive.
  • 1… - tell the system to count from 1 to the end of index.


One-Sided Half Open Range Operator

One-sided half open range operator can be written as


..<10




For half open range operator, Swift only support the one-sided half open range operator with the end index included as shown above.


We cannot do (0..<) as shown in the screen below.

Listed below is an example of application of one-sided range operator.


let someArrayB = [1,2,3,4,5,6,7,8,9,10]
someArrayB[0]
someArrayB[9]
someArrayB.count
someArrayB.last

someArrayB[3...7]
someArrayB[1...]
someArrayB[...7]

someArrayB[3..<7]
someArrayB[..<5]




Limit of One-Sided Range Operator

We can also use one-sided range operator in any other context besides array subscripts. However, if the range is one-sided, what are the limits? The range is limited to the maximum and the minimum of an integer.


Please see example below:


// Define range from 1 t0 maximum of an Int can handle
let someRange3 = 1...
someRange3.contains(100)
someRange3.contains(100000000)
let rangeMax = Int.max
someRange3.contains(rangeMax)

// Define range from Int minimum to 100 inclusive
let someRange4 = ...100
someRange4.contains(10000)
someRange4.contains(100)
someRange4.contains(-11000000)
let rangeMin = Int.min
someRange4.contains(rangeMin)

// Define range from Int minimum to 100 inclusive
let someRange5 = ..<1000
someRange5.contains(1000)
someRange5.contains(999)
someRange5.contains(-766999)
someRange5.contains(rangeMin)




Please note that if we enter a number that is beyond the limits of an integer, runtime or compile error will occurs.


Logical Operator

In Swift, we support 3 logical operator, they are the NOT, AND and OR.


  • NOT operator is denoted as !
  • AND operator is denoted as &&
  • OR operator is denoted as ||


Logical NOT Operator

We can use logical NOT operator as a unary prefix. A NOT in front of true will be false and vice versa. The syntax of using NOT operator is as follows:


!<variable/data>


Example


let myTruth = false

let myNewTruth = !myTruth

print("My truth is \(myTruth) and my new truth is \(myNewTruth).")




Logical AND Operator

We use logical AND operator as a binary operator in between 2 operand. The syntax of using AND operator is as follows:


<variable/data> && <variable/data>


Example


let myDoorCode = true

let myFingerPrint = false

if myDoorCode && myFingerPrint == true {
   print("Access Granted")
} else {
   print("Access Denied")
}




Note:
Please note that for AND operator, the system use short circuit evaluation. This means that the system will evaluate the left most conditional statement and if the first evaluation is false, the system will stop further evaluation because even if the second evaluation is true the result will still be false. We should place the statement that commonly generate false result on the left hand side of evaluation to increase efficiency.


Logical OR Operator

We use logical OR operator as a binary operator in between 2 operand. The syntax of using OR operator is as follows:


<variable/data> || <variable/data>


Example:


let myDoorCode = true

let myFingerPrint = false

if myDoorCode || myFingerPrint == true {
   print("Access Granted")
} else {
   print("Access Denied")
}




Note:
Similarly, for OR operator, the system also use short circuit evaluation. This means that the system will evaluate the left most conditional statement and if the first evaluation is true, the system will stop further evaluation because even if the second evaluation is false the result will still be true. We should place the statement that commonly generate true result on the  left hand side of evaluation to increase efficiency.


Compound Logical Operator

We use multiple logical operator to form a compound expression. The system will evaluate the leftmost expression first and to the right. Please note that however && has precedence over ||. You need to evaluate && operation from left to right and then evaluate || from left to right.


Example:


let myDoorCode = true

let myFingerPrint = false

let keyOverride = true

let overridePassCode = true

if myDoorCode && myFingerPrint || keyOverride && overridePassCode {
   print("Access Granted")
} else {
   print("Access Denied")
}




In the example above, the system allowed 2 combination for user to enter the gate. Either the user enter the door code correct together with a correct fingerprint scan or; the user can use manual override key together with a correct override passcode.


To improve readability, the above example should be written as follows:




Operator AND has Precedence Against Operator OR

While we construct compound statement, please be aware that operator AND has a higher precedence level compared to operator OR.


Please check the example below:


// The following evaluate to true since AND has precedence over OR
true || false && false

// To produce the false result we must use () as shown below
(true || false) && false




More example:


let condition1 = true
let condition2 = false
let condition3 = true
let condition4 = false

condition1 || condition2 && condition3 && condition4
// Please note that && has precedence over || You need to evaluate && operation from left to right and then evaluate || from left to right




Example:


true || false && true && false
true && false || false || true
true && true || false && false
false || true && true || false




Operator Precedence



Operator precedence is the order of computing the operator. Consider the example below:


Example:
42 - 20 * 12 / 3 + 5 * 6 + 54
// The result is 46


For some programming language, all the arithmetic operator got the same precedence; this means that the system will evaluate the computation in the order from left to right. The result will be 612 if we evaluate from left to right.


Most programming language however, adopt the common precedence where multiplication and division have the same precedence but they are placed in a higher order than addition and subtraction.


In the example above, we should evaluate the multiplication and division first from left to right. After multiplication and division are evaluated, then we start evaluation addition and subtraction from left to right.


To change the order of precedence, such as we want to perform a subtraction first, we can add parenthesis to affect the order. Parenthesis has a higher precedence than the other arithmetic operator.


Example:


42 - 20 * 12 / 3 + 5 * 6 + 54
(42 - 20) * 12 / 3 + 5 * (6 + 54)




In the example above, the system will perform computation in the parenthesis first before resuming normal arithmetic operation. The result is different.


Similarly, we can also use parentheses to affect the order of evaluation when we use logical operator as shown in the previous section.


Listed below is a simplified table of the operator precedence. All operators under the same group have the same precedence. Left associative means the system will evaluate the expression from left to right. Right associative means that the system will evaluate the expression from right to left. Operator on the top of the list has higher precedence than the operator at the bottom of the list.
Precedence group
Operator
Description
Associativity
Primary Expression
( )
Parenthesis
Left associative
Prefix Operator
!
-
..<
...
Logical NOT
Unary Minus
Half-open range
Closed range
None
None
None
None
Postfix Operator
...
Closed range
None
Multiplication
*
Multiply
Left associative

/
Divide
Left associative

%
Remainder
Left associative
Addition
+
Add
Left associative

-
Subtract
Left associative
Range formation
..<
Half-open range
None

...
Closed range
None
Nil-Coalescing
??
Nil-Coalescing
Right associative
Comparison
<
Less than
None

<=
Less than or equal
None

>
Greater than
None

>=
Greater than or equal
None

==
Equal
None

!=
Not equal
None
Logical conjunction
&&
Logical AND
Left associative
Logical disjunction
||
Logical OR
Left associative
Ternary
?:
Ternary conditional
Right associative
Assignment
=
Assign
Right associative

*=
Multiply and assign
Right associative

/=
Divide and assign
Right associative

%=
Remainder and assign
Right associative

+=
Add and assign
Right associative

-=
Subtract and assign
Right associative
Function Arrow
->
Function Arrow
Right associative


Explicit Parentheses

For complex expression, it is better to use bracket or parentheses to organize the expression. It also improve code readability.


Example:


let condition5 = true
let condition6 = false
let condition7 = true
let condition8 = false

condition5 || condition6 && condition7 && condition8
// Evaluate to true as && take precedence before ||

// With parentheses the result may be different
(condition5 || condition6) && (condition7 && condition8)



***