Swift Operators

CocoaheadsSKG

Dimitri James Tsiflitzis

What is an operator?

  • Most programming languages use operators.
  • An operator is a symbol or phrase that represents a functionality.
  • For instance, i = 1 in Swift uses the assignment operator = which has the functionality of storing the value 1 in the variable i.
  • Many languages also have phrases that are operators, like sizeof in C, and the type-cast operator as in Swift.

Arity

  • The operation represented by an operator accepts a number of operands.
  • From Objective-C, we know operators with arity from 1 to 3.
  • Unary operators represent operations with one operand. Examples in Objective-C include the negation operator !, the increment operator ++, and the sizeof operator.
  • Binary operators represent operations with two operands. The majority of Objective-C’s operators are binary operators, like +, -, *, /, <, <=, >=, >, ==, !=, &&, =, +=, -=, and so on.

Arity

  • Ternary operators represent operations with three operands. In Objective-C and Swift, there is only one ternary operator: The conditional expression ? : .

Placement

  • Prefix
    • !: Logical NOT
  • ​Infix
    • << Bitwise left shift
    • * Multiply
    • + Add
    • is Type check
    • =    Assign

Source: https://developer.apple.com/reference/swift/swift_standard_library_operators

Overloading

  • Operators are often overloaded, meaning they work for different types. In C/Objective-C for instance, the + operator is overloaded to allow adding two int and two double, among others. In contrast, functions in C/Objective-C are never overloaded.[citation needed]

De facto operators defined by the Swift language

  • .: Member Access
  • ?: Optional
  • !: Forced-Value
  • []: Subscript
  • []=: Subscript Assignment

Precedence and Associativity

let a = 3
let b = 4
let c = a * a + b * b // c = (a * a) + (b * b)
let d = b — a + b     // d = (b - a) + b

Operators have a precedence, and an associativity that determine the order in which they are executed.

Precedence and Associativity

var a = false
var b = false
var c = true
if a == b == c {     // COMPILER ERROR
    print("WAT")
}

Operators can either be left-associative, right-associative, or non-associative. 

Short-Circuit Evaluation

func foo() -> Bool {
    print("foo() called")
    return true
}
false && foo()

A couple of operators in Objective-C and Swift provide short-circuit evaluation. That means an operand is only calculated if necessary.

*I once impressed an interviewer with this one

Overloading

func * (left: String, right: Int) -> String {
    if right <= 0 {
        return ""
    }

    var result = left
    for _ in 1..<right {
        result += left
    }

    return result
}

"a" * 6 
// "aaaaaa"

Swift has the ability to overload operators such that existing operators, like +

 

Overloading Rant

  • A "controversial" language feature.
  • Please consider
    • func +(left: [Double], right: [Double]) -> [Double] {}
    • Output:
      • [1, 2] + [3, 4] // [1, 2, 3, 4]
      • or
      • [1, 2] + [3, 4] // [4.0, 6.0]
      • etc. etc.

Overloading Rant

func <<<T> ( left: inout [T], right: T) -> [T] {
    left.append(right)
    return left
}

Custom Operators

Consider the arithmetic operator found in many programming languages, but missing in Swift **, which raises the left hand number to the power of the right hand number

Custom Operators

  • Infix specifies that it is a binary operator, taking a left and right hand argument
  • operator is a reserved word that must be preceded with either prefix, infix, or postfix
  • ** is the operator itself
infix operator ** : MultiplicationPrecedence

*command click import swift to check precedence

Custom Operators

infix operator ** 
func ** (left: Double, right: Double) -> Double {
    return pow(left, right)
}

2 ** 3 
// 8

When creating custom operators, make sure to also create the corresponding assignment operator, if appropriate:

infix operator **=
func **= ( left: inout Double, right: Double) {
    left = left ** right
}

Use of Mathematical Symbols

Or consider the ± operator, which can be used either as an infix or prefix to return a tuple with the sum and difference:

infix operator ±
func ± (left: Double, right: Double) -> (Double, Double) {
    return (left + right, left - right)
}

prefix operator ± {}
prefix func ± (value: Double) -> (Double, Double) {
    return 0 ± value
}

2 ± 3
// (5, -1)

±4
// (4, -4)

Use of Mathematical Symbols

Consider a set union ∪

let set1: Set<Int> = [1, 5]
let set2: Set<Int> = [2, 5]
let set1: set1 ∪ set2
print(set3) // [1, 2, 5]

Precedence

Precedence

precedencegroup PowerMultiplicationPrecedence {
  lowerThan: MultiplicationPrecedence
  associativity: left
}

infix operator **: PowerMultiplicationPrecedence


// in < 2.3
infix operator ** { associativity left precedence 160 }

Guidelines for Swift Operators

  1. Don’t create an operator unless its meaning is obvious and undisputed. Seek out any potential conflicts to ensure semantic consistency.
  2. Custom operators should only be provided as a convenience. Complex functionality should always be implemented in a function, preferably one specified as a generic using a custom protocol.
  3. Pay attention to the precedence and associativity of custom operators. Find the closest existing class of operators and use the appropriate precedence value.
  4. If it makes sense, be sure to implement assignment shorthand for a custom operator (e.g. += for +).

Lessons Learned

Lesson One

Operators are precious and expensive. They involve significant mental costs for creating code for reading code, and maintaining code. Use operators sparingly.

Lesson Two

An operator that is sourced from foundational concepts like math establishes important context and association cues.

Lesson Three

If you’re going to dive in and use an operator, select non-trivial functionality with the biggest impact possible.

Lesson Four

A great operator that’s impossible to type isn’t going to get used.

Lesson Five

Think global. First, prefer symbols that can be as easily entered on the keyboard.

Lesson Six

When you adopt an operator use it, use it.

Lesson Seven

Prefer usable code to pretty code.

Further reading


https://news.realm.io/news/slug-erica-sadun-operators-strong-opinions/


http://nshipster.com/swift-operators/


https://medium.com/swift-programming/facets-of-swift-part-5-custom-operators-1080bc78ccc

Ευχαριστούμε

Swift Operators

By tsif

Swift Operators

  • 266