Last active
April 7, 2022 20:42
-
-
Save ajRiverav/9fcab7b44cd17c022afa6197f862fc4b to your computer and use it in GitHub Desktop.
Type erasure in Swift: Example using Sequence and AnySequence, which are provided by the Swift Standard Library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// DO NOT USE - WORK IN PROGRESS | |
// | |
import Foundation | |
// "A sequence is a list of values that you can step through one at a time. The most common way to iterate over the elements of a sequence is to use a for-in loop.", per the documentation. | |
// Let's say one wanted to iterate over the sequence of strings ["apple", "bird", "cake"], such that | |
// the following code prints each value: | |
for value in sequence { | |
print(value) | |
} | |
// Let's attempt to create the sequence: | |
let sequenceString: Sequence = Sequence(["apple", "bird", "cake"]) | |
// The line above produces the error: | |
// 'Sequence' cannot be constructed because it has no accessible initializers | |
// Let's then try to specify the type of the sequence elements (which is string): | |
let sequenceString: Sequence<String> = Sequence(["apple", "bird", "cake"]) | |
// The line above produces the error: | |
// Cannot specialize non-generic type 'Sequence' | |
// Why are we getting this errors? | |
// Upon inspection of `Sequence`, we see it is a protocol and has three requirements: | |
// 1) method makeIterator() -> Self.Iterator (Returns an iterator over the elements of this sequence) | |
// 2) associatedtype Iterator (A type that provides the sequence’s iteration interface and encapsulates its iteration state) | |
// 3) associatedtype Element (A type representing the sequence’s elements) | |
// Of interest if the last requirement. We can see that `Sequence` can handle different element types (via its associatedtype requirement) but -and this is key to understand- one cannot declare an instance of it as `Sequence<String>`, hence the compiler warning "Cannot specialize non-generic type 'Sequence'". | |
// So, what can one do? One option (the one that gives birth to the creation of `AnySequence`) is to create a new type which would allow one to implement protocol `Sequence`, including -and this is another key concept to understand- its associated type `Element`. The mechanics of this look like: | |
struct AnySequence: Sequence { | |
} | |
let sequenceString: Sequence<String> = Sequence(["apple", "bird", "cake"]) | |
let anySequenceString: AnySequence<String> = AnySequence(["apple", "bird", "cake"]) | |
let anySequenceInt: AnySequence<Int> = AnySequence([1, 2, 3]) | |
print(anySequenceString) | |
// AnySequence<String>(_box: Swift._SequenceBox<Swift.Array<Swift.String>>) | |
print(anySequenceInt) | |
// AnySequence<Int>(_box: Swift._SequenceBox<Swift.Array<Swift.Int>>) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
initial commit