Swift Tip: Collection Protocols
With Swift 5 officially released ๐, we're busy updating Advanced Swift for an expanded fourth edition. This week, we'd like to share a brief overview of collection protocols, which we'll be discussing in more depth in the book.
In Swift, there are a number of collection protocols, each with their own features:
-
Sequence provides iteration. It allows you to generate an iterator, but there are no guarantees about whether the sequence is single-pass (e.g. reading from standard input) or multi-pass (iterating over an array).
-
Collection extends
Sequence
. It guarantees that the sequence is multi-pass, and allows you to look up elements by their index. It also adds aSubSequence
type, which is a collection itself. -
MutableCollection adds the ability to mutate an element through a subscript in constant time. It does not allow you to add or remove elements. Notably,
String
does not conform because characters in a string are variable-width (which means replacing a character could take linear time).String.UnicodeScalarView
does conform. -
RangeReplaceableCollection adds the ability to replace a contiguous range of elements in the collection. By extension, this also adds methods like
append
,remove
, and so on. Many mutable collections are range replaceable as well, but there are exceptions. Most notably,Set
andDictionary
don't conform, but types likeString
andArray
do conform. -
BidirectionalCollection adds the ability to iterate backwards through a collection. For example, a
Dictionary
doesn't allow reverse iteration, and doesn't conform, but aKeyValuePairs
(previously calledDictionaryLiteral
) does. Backwards iteration is critical for some algorithms. -
RandomAccessCollection extends
BidirectionalCollection
and adds the ability to compute with indices more efficiently: it requires that measuring the distance between indices and moving indices by a certain distance takes constant time. For example, anArray
is a random access collection, but aString
is not: computing the distance between two string indices takes linear time. -
LazySequenceProtocol is similar to a sequence, but iteration becomes lazy. This is mostly useful for writing algorithms in a functional style: you can take an infinite sequence, filter it, and then take the first element.
-
LazyCollectionProtocol is the same as
LazySequenceProtocol
, but for collections.
When you write your own algorithms, it can be very useful to have this protocol hierarchy in mind: if you can write an algorithm on one of the protocols towards the top of the hierarchy, more types will get the same functionality.
The new edition of Advanced Swift will be released by the end of April. If you've already bought the Ebook, this will be a free upgrade. ๐
Our current Swift Talk mini-series looks at String Interpolation in Swift 5, which we use in our Swift Talk backend to automatically insert placeholders in SQL queries. The first episode is public.
Swift Talk subscribers can explore many of these topics in our collection, Swift, The Language. To support our work, and access all episodes, become a subscriber.