Advanced Operators

Introduction

Welcome to Lesson 2 of Advanced Swift. Throughout the previous lessons, I’ve given you a little taste about Advanced Operators. It’s your turn.

Problem

Learn how to create custom operators

Inout

Note: Function parameters are constants by default.

Let us create a function whose parameter is decorated with inout.

  1. func enterSomething(_ a: inout Int) {
  2. a += 1
  3. print(a)
  4. }

inout parameters can be modified. Let us execute the function.

  1. var number = 10
  2. enterSomething(&number)

Let us check number

  1. print(number) // 11

It has been mutated by the function even though it was used as the parameter.

Design Prefix and PostFix Operators

Let us get to the objective.

Prefix Operator

Let us create one. Define an operator.

  1. prefix operator

Add logics to the operator.

  1. prefix func √(number: Double) -> Double {
  2. return sqrt(number)
  3. }
  4. 1000000 // 1000
  5. 10000234234 // Some number

Let us a create a silly one.

  1. prefix operator ©
  2. prefix func ©(enterWord: String) -> String {
  3. return "\(enterWord)™"
  4. }

Let us apply

  1. ©("Bob the Developer")
  2. // "Bob the Developer™"

Important: Click opt-g to create ©

PostFix Operator

Postfix is an operator that comes after the value.

  1. let myName: String? = "Bob"
  2. myName!

Let us create one.

  1. postfix operator =!
  2. postfix func =!(value: String?) -> String {
  3. guard let unwrappedValue = value else {
  4. return ""
  5. }
  6. return unwrappedValue
  7. }

Let us apply.

  1. myName=!
  2. // "Bob"

Let us create an operator, %% that determines whether the number is odd or even.

  1. postfix operator %%
  2. postfix func %%(enterNumber: Int) -> String {
  3. return enterNumber % 2 == 0 ? "Even" : "Odd"
  4. }

Let us use the operator.

  1. Int(arc4random())%% // "Even" or "Odd"

Infix Operator

This is the real deal. Let us take a look at a couple default examples.

Group Precedence Examples
BitwiseShiftPrecedence precedence 160 <<, >>
MultiplicationPrecedence associativity left precedence 150 /, %, &, *
AdditionPrecedence associativity left precedence 140 +, -
RangeFormationPrecedence precedence 135 ..<, …
CastingPrecedence precedence 132 is, as
ComparisonPrecedence precedence 130 <, <=, ==, !=, ===
LogicalConjunctionPrecedence associativity left precedence 120 &&
NilCoalescingPrecedence associativity right precedence 110 ??
TernaryPrecedence associativity right precedence 100 ?
AssignmentPrecedence associativity right precedence 90 =, *=, /=, +=

Old Method

Let us create one.

  1. infix operator ** { associativity left precedence 130 }

Let us add logics.

  1. func ** (left: Double, right: Double) -> Double {
  2. return pow(left, right)
  3. }

Let us call the operator.

  1. 2 ** 3 // 8
  2. 2 ** 10 // 1024

Swift 3.0

Precedence value is no longer used. Instead, the priority of custom operators is determined relatively.

Let us a create a group called, CustomOperatorPrecedence.

  1. precedencegroup CustomOperatorPrecedence {
  2. higherThan: AdditionPrecedence
  3. lowerThan: MultiplicationPrecedence
  4. associativity: left
  5. }

Define an operator, ???? that conforms to CustomOperatorPrecedence.

  1. infix operator ????: CustomOperatorPrecedence

The ???? is used to generate a random number.

  1. func ???? (left: UInt32, right: UInt32) -> Double {
  2. let lower : UInt32 = left
  3. let upper : UInt32 = right
  4. let randomNumber = arc4random_uniform(upper - lower) + lower
  5. return Double(randomNumber)
  6. }

Execute the operator.

  1. 1 ???? 10 // 10
  2. 1 ???? 124234324 // 124234324

Operator Overloading

You may override an operator that is pre-defined by Swift engineers. Let us attempt to add an extra functionality with * as shown below.

  1. "a" * 10
  2. "aaaaaaaaa"

Add extra feature.

  1. func * (left: String, right: Int) -> String {
  2. guard right >= 0 else {
  3. print("Make sure enter number higher 0")
  4. return ""
  5. }
  6. var result = String()
  7. for _ in 1..<right {
  8. result += left
  9. }
  10. return result
  11. }

Execute the operator

  1. "Bob" * 10 // "BobBobBob..."

Another Example

Let us attempt to achieve the effect as shown by operator below.

  1. [1, 2] + [3, 4] // [4.0, 6.0]

Add logics to the operator.

  1. func +(left: [Double], right: [Double]) -> [Double] {
  2. var sum = [Double](repeatElement(0.0, count: left.count))
  3. print(left.enumerated())
  4. for (i, _) in left.enumerated() {
  5. sum[i] = left[i] + right[i]
  6. }
  7. return sum
  8. }

Source Code

8002_advanced_operators

References

Swift Operators by Matt Thompson

The Swift Programming Language (Swift 3.1) - Advanced Operators

Conclusion

First, you’ve learned that inout parameters can be modified within the function. Second, you’ve learned how to create prefix and postfix operators by defining them first and adding the logic second. Lastly, you’ve learned the old way of creating infix operators with the definite precedence value. Now, however, you define the precedence value relative to default operator groups. However, be careful not to overuse custom operators. Once you use them, you should create documents for your teammates and for yourself.

In the following lesson, you will the final aspect of Swift Error Handling.

Note: Learn Swift with Bob is available on Udemy. If you wish to receive a discount link, you may sign up here.