In the previous article, while trying to understand a major difference between Arrays and Dictionaries, we created our own sequence. But we can go deeper.
Sequence is the most basic set notion given by the Swift standard library. There is a more evolved one.
A collection is defined as follow :
A multi-pass *sequence* with addressable positions
As we saw previously, a sequence is a type that can be iterated with a for … in loop. It doesn’t need that the elements might be iterated over several times. And it doesn’t need that we give a way to access directly an element.
Collections requires those last two points. As a side effect, it no longer allows us to have an infinite number of elements.
To be a collection a type must conform to the CollectionType protocol.
In our case, the Section type (see part 1) already conforms to the SequenceType protocol. We just have to make it Indexable.
We won’t go in the details of the Index protocol, its name is pretty self-explanatory. In our case it’s an Int. Let’s create a startIndex and an endIndex
The endIndex has to be after the last element. It allows to define an empty collection with startIndex = endIndex.
So, are we done?
In fact, one requirement of the Indexable protocol is missing. A subscript. That takes an Index as a parameter and returns a non-optional Element. Does that ring a bell? It’s the same signature than the Array’s subscript that crashes at runtime! So that’s where it comes from… 🤔
To get back to our Section, we already implemented a subscript with an Int as a parameter. We’ll have to replace it to conform to Indexable. We still can implement our convenient safe subscript.
By conforming to both SequenceType and Indexable, we are now conforming to CollectionType.
As with SequenceType, we’ll get a couple of methods. Here are some of those :
We get indexOf thanks to our Elements being Equatable. It might look less impressive than the ones provided by SequenceType but hey, it’s free!
We created our own collection, which is great, but what about that difference of behavior between Arrays and Dictionaries we talked about in introduction of part 1? We saw that Array’s dangerous subscript was coming from the Indexable protocol, but what about Dictionaries?
Dictionaries, like Arrays are a collection, as Swift defines it. They both conform to CollectionType. So Dictionaries are also required to provide an ‘unsafe’ subscript that takes an Index and returns a non optional Element. The one we’re used to is just a convenience subscript.
Here are the two subscripts of the Dictionaries in the standard library.
A simple example shows that it is also really easy to get a crash with Dictionaries.
advancedBy is a method from the Index protocol (ForwardIndexType protocol to be exact) that allows to go through the indexes.
The last question that remains is why Indexable requires a subscript that may crash? Simply for performance reason, it costs too much to check the validity of the given index. Crashing is faster :)
To end my first article, I’d like to thank Santosh Rajan for making me part of the Swift Programming writers. Special thanks also to @NatashaTheRobot, @ericasadun, @ashfurrow, @simjp, @aligatr & @cocoaphony for their help, Swift community kicks ass! 😎