Swift built-in data types and data structures

If you are reading this book, you are probably very familiar with Swift's built-in data types and data structures. However, to really unleash their power, we need to understand how they are implemented in the Swift standard library.

The Swift standard library defines several standard data types such as Int, Double, and String. In most languages, these types are implemented as primitive types, which means that they cannot be extended or subclassed. In Swift, however, these types are implemented in the Swift standard library as structures, which means that we can extend these types just as we can with any other type that is implemented as a structure.

Swift also defines several standard data structures, such as the array, dictionary, and set. Just like the built-in data types, these are also implemented as structures in the Swift standard library.

We will be discussing extensions in great detail in Chapter 5, Let's Extend Some Types, but for right now, let's quickly see what we can do with extensions. As we will see, it is important to understand that data types and data structures in Swift are implemented with structures.

Let's say that, in our application, we needed to calculate the factorial of some integers. A factorial is written as 5!. To calculate a factorial, we take the product of all the positive integers less than or equal to the number. To calculate the factorial of 5, we will do as follows:

5! = 5*4*3*2*1
5! = 120

We could very easily create a global function to calculate the factorial and we would do that in most languages. But extensions in Swift give us a better way to add functions like this and, since the Int type has been implemented as a structure, we can extend it, as shown in the following example:

extension Int {
    func factorial() -> Int {
        var answer = 1
        for x in self.stride(to: 1, by: -1) {
            answer *= x
        }
        return answer
    }
}

We could now calculate the factorial of any integer, as follows:

var f = 10
print(f.factorial())

It is sometimes better to extend a protocol rather than a single type, as shown here, because when we extend a protocol, all the types that conform to this protocol will receive the functionality rather than just the single type. We will discuss extensions in greater detail in Chapter 5, Let's Extend Some Types. The key to keep in mind here is that any type derived from a named type can be extended.