A sequence is a list of values that you can step through one at a time.
Swift sequences are one of the most fundamental concepts present in the language and we can use it to create custom collection types. The biggest advantage of using sequences as foundation blocks for custom collection types is that we get direct access to highly optimised versions of a bunch of algorithms right out of the box. Since Sequences forms a core foundation block while creating custom collection types, it becomes really important to know Sequences in detail.
In this article we will dive deeper inside the
Sequence protocol, discover
UnfoldSequence and use it to create our
Sequence types with minimal code.
Sequence Protocol and conformance
According to apple documentation:
Sequences provide sequential, iterated access to its elements.
As discussed earlier, making your own custom types conform to
Sequence enables many useful operations, like
in looping and the
contains method, without much effort. To add
Sequence conformance to your own custom type, add a
makeIterator() method that returns an iterator.
Alternatively, if your type can act as its own iterator, implementing the requirements of the
IteratorProtocol protocol and declaring conformance to both
IteratorProtocol are sufficient.
Ranges are all sequences, and as discussed above, it doesn’t take that much to be considered a sequence.
Sequences return a set of values one at a time, and those values can be “used/consumed” making revisiting those values optional.
A sequence protocol requires a factory method that returns an
Iterator type as shown in the code below:
An iterator is a type that conforms to Iterator protocol. The protocol has a mutating method next() that returns individual values one after the other until it can’t anymore, in which case it returns a nil.
While looping over arrays or any sequence types, swift calls
makeIterator()and then repeatedly calls
next() to loop over the items in the sequence. Let’s build our own
Sequence in code. Since we know that a
Sequence requires an
Iterator type, we will start by creating an
Iterator as follows:
The basic iterator that we created returns the same string always which means that
iterator.next() always returns the
stringValue property and it will never return a
nil to indicate the end of
StringIterator conforms to
IteratorProtocol as required.
Since we have an
Iterator, we can now create a
Sequence as follows:
makeIterator() factory method returns a
StringIterator and we have used the
prefix() function on
StringSequence to pick first 5 values. The result of the
Addressing boilerplate code
In the previous section we created our sequence type but there is a lot of boiler plate code. Swift contains a lot of helpers that enable us to create custom sequences easily. The
sequence function is one such helper. The sequence function takes an initial state and a closure for computing the next value. This eliminates the need for an explicit iterator. The method returns a sequence that starts with
first and continues with every value returned by passing the previous element to
next as shown in the definition below:
func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldFirstSequence<T>
The type returned by
UnfoldSequenceconforms to both sequence and the iterator protocol so we don’t have to do this explicitly.
UnfoldFirstSequence is just a
typealias as shown below:
typealias UnfoldFirstSequence<T> = UnfoldSequence<T, (T?, Bool)>
The first element in the sequence is always
first, and each successive element is the result of invoking
next with the previous element. The sequence ends when
next never returns
nil, the sequence is infinite.
This function can be used to replace many cases that were previously handled using C-style
Now, we can use this shorthand syntax to create the same sequence as follows:
The result of executing the code above will print following to the console:
In the upcoming articles we will use sequences to understand swift collections and create custom collections to use in our apps.
For other updates you can follow me on Twitter on my twitter handle @NavRudraSambyal.
Thanks for reading, please share it if you found it useful 🙂