Skip to content

Instantly share code, notes, and snippets.

@ajRiverav
Last active April 7, 2022 20:42
Show Gist options
  • Save ajRiverav/9fcab7b44cd17c022afa6197f862fc4b to your computer and use it in GitHub Desktop.
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
//
// 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>>)
@ajRiverav
Copy link
Author

ajRiverav commented Apr 7, 2022

initial commit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment