Even though most operators in Swift look and behave the same way they do in other programming languages, there are a few you may not know about or that behave in a slightly different manner.
Ternary Conditional Operator
If you have any experience programming, then you probably know about the ternary conditional operator. In Swift, the behavior of this operator is identical to that in C and Objective-C.
This operator is often used to replace simple if-else
statements. In the example below, the result of the assignment that uses the ternary conditional operator is identical to that of the if-else
statement. I am sure you agree that the example that uses the ternary conditional operator is more elegant and easier to read.
var message = ""
let price = 10.0
if price > 20.0 {
message = "expensive"
} else {
message = "bargain"
}
message = price > 20.0 ? "expensive" : "bargain"
Nil Coalescing
The nil coalescing operator does not exist in C and Objective-C. The idea is simple, though. Take a look at the following example.
var a: Int?
var b = 5
let c = a ?? b
The ??
or nil coalescing operator inspects the value of a
. If a
has no value, it defaults to the value stored in b
. In the above example, c
is assigned the value of 5
.
What I like about the ??
operator in Swift is that it implicitly unwraps an optional and only assigns a value if the optional has a value. The above example shows how that works.
Range Operators
Swift defines two range operators:
...
or closed range operator..<
or half-open range operator
The difference is obvious as illustrated by the example below. The body of the first for-in
loop is executed eleven times whereas that of the second for-in
loop is executed only ten times.
for i in 0...10 {
print(i)
}
for i in 0..<10 {
print(i)
}
The ...
or closed range operator includes the final value of the range whereas the ..<
or half-open operator excludes the final value of the range.
Range operators are very useful for looping over a range of values. But why does Swift define two range operators? This is primarily for convenience. Take a look at the following example.
let numbers = [49, 27, 4, 32, 23, 431, 5]
for i in 0..<numbers.count {
print(numbers[i])
}
The example is somewhat contrived because there are better ways to enumerate the values of an array. The point is that half-open range operators are convenient for looping over collections that are zero-based, such as arrays.
Equality & Identity Operators
Chances are that you are already familiar with Swift's equality operators, ==
and !=
. But Swift also defines a pair of identity operators, ===
and !==
. Take a look the next example to learn about the differences.
import Foundation
let arr1 = NSArray(array: [1, 2])
let arr2 = NSArray(array: [1, 2])
let arr3 = arr2
print(arr1 == arr2) // true
print(arr1 === arr2) // false
print(arr2 === arr3) // true
The ==
or equality operator checks whether the two operands are equal. What equal means for an object depends on the implementation of the class or structure. For the NSArray
class, the contents of the arrays are compared. In the above example, arr1
is equal to arr2
because the values stored in the arrays are equal.
The ===
or identity operator compares the identity of the objects. It checks whether the operands refer to the same object. As you can see, arr1
and arr2
do not refer to the same object, despite the objects being equal. The identity of arr2
and arr3
is the same, though. Both constants point to the same object.
Subscript Syntax
Even though the term subscript may sound foreign to you, chances are that you have already used Swift's subscript syntax. Take a look at the next example to learn what subscript syntax looks like in Swift.
let cities = ["New York", "Paris", "Berlin", "London"]
print(cities[2])
The []
or subscript syntax should look familiar if you have worked with arrays and dictionaries. The reason I bring it up is to show you how to use it in custom classes and structures.
Take a look at the following example in which we define the Item
and ShoppingList
structures. To add support for subscript syntax to the ShoppingList
structure, we write a subscript definition using the subscript
keyword. This enables us to query ShoppingList
instances using subscript syntax. Note that we do not use the func
keyword when creating a subscript definition.
struct Item {
var price = 0.0
var name: String
init(name: String) {
self.name = name
}
}
struct ShoppingList {
var items = [Item]()
mutating func addItem(_ item: Item) {
items.append(item)
}
subscript(index: Int) -> Item? {
return (index < items.count) ? items[index] : nil
}
}
This implementation allows us to use subscript syntax on instances of the ShoppingList
structure.
var shoppingList = ShoppingList()
if let item = shoppingList[0] {
print(item.name)
} else {
print("No Item Found")
}
shoppingList.addItem(Item(name: "Milk"))
if let item = shoppingList[0] {
print(item.name)
} else {
print("No Item Found")
}
The subscript definition in the above example accepts a value of type Int
. If you want subscript syntax for the ShoppingList
class to work with String
values as well, then you need to create another subscript definition. That is how the Dictionary
structure, defined in the Swift Standard Library, adds support for subscript syntax.
What's Next?
The Swift programming language defines a wide range of operators. Most of them are pretty easy to understand, but Swift also defines a slew of pretty advanced operators. If you want to learn more about operators in Swift, I recommend taking a look at the language reference for basic operators and advanced operators.
Questions? Leave them in the comments below or reach out to me on Twitter.