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
- Don’t create an operator unless its meaning is obvious and undisputed. Seek out any potential conflicts to ensure semantic consistency.
- 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.
- Pay attention to the precedence and associativity of custom operators. Find the closest existing class of operators and use the appropriate precedence value.
- 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
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