Swift Sequences & Collections
@greg3z
let array = [1, 2, 3]
let array = [1, 2, 3]
array[7] 😭
let dic = ["a": 1, "b": 2]
let dic = ["a": 1, "b": 2]
dic["z"] 😎
[] -> subscript
struct Array<Element> {
subscript(index: Int) -> Element
}
struct Dictionary<Key: Hashable, Value> {
subscript(key: Key) -> Value?
}
subscript(index: Int) -> Element?
subscript(safe index: Int) -> Element?
subscript(safe index: Int) -> Element?
array[safe: 2]
extension Array {
subscript(safe i: Int) -> Element? {
return i >= 0 && i < count ? self[i] : nil
}
}
let array = [1, 2, 3]
let array = [1, 2, 3]
array[safe: 7] 😎
Custom collection?
A type that I did myself
struct Section<T> {
let title: String
let elements: [T]
}
struct Section<T> {
let title: String
let elements: [T]
subscript(index: Int) -> T? {
return elements[safe: index]
}
}
let cars = ["911", "Cayman", "Cayenne"]
let section = Section(title: "Porsche", elements: cars)
let cars = ["911", "Cayman", "Cayenne"]
let section = Section(title: "Porsche", elements: cars)
section[1]
// Optional("Cayman")
Sequence
A type that can be iterated with a `for`...`in` loop
protocol SequenceType {
func generate() -> GeneratorType
}
protocol GeneratorType {
func next() -> Element?
}
struct ArrayGenerator<T>: GeneratorType {
func next() -> T? {
return something
}
}
struct ArrayGenerator<T>: GeneratorType {
let array: [T]
var currentIndex = 0
init(_ array: [T]) {
self.array = array
}
mutating func next() -> T? {
return array[safe: currentIndex++]
}
}
struct Section<T>: SequenceType {
let title: String
let elements: [T]
func generate() -> ArrayGenerator<T> {
return ArrayGenerator(elements)
}
}
var generator = section.generate()
while let element = generator.next() {
}
for element in section {
}
var generator = section.generate()
while let element = generator.next() {
}
for element in section {
}
let cars = ["911", "Cayman", "Cayenne"]
let section = Section(title: "Porsche", elements: cars)
for car in section {
}
// 911
// Cayman
// Cayenne
for (index, car) in section.enumerate() {
}
// 0 911
// 1 Cayman
// 2 Cayenne
section.minElement()
// 911
section.maxElement()
// Cayman
section.sort()
// ["911", "Cayenne", "Cayman"]
section.contains("911")
// true
section.filter {
$0.characters.count > 3
}
// ["Cayman", "Cayenne"]
section.map {
$0.characters.count
}
// [3, 6, 7]
section.reduce(0) {
$0 + $1.characters.count
}
// 16
Collection
A multi-pass *sequence* with addressable positions
protocol CollectionType : Indexable, SequenceType {
}
protocol Indexable {
var startIndex: Index { get }
var endIndex: Index { get }
}
struct Section<T>: Indexable {
let title: String
var elements: [T]
var startIndex: Int {
return 0
}
var endIndex: Int {
return elements.count
}
subscript(index: Int) -> T? { … }
func generate() -> ArrayGenerator<T> { … }
}
protocol Indexable {
var startIndex: Index { get }
var endIndex: Index { get }
subscript(position: Index) -> Element { get }
}
struct Section<T>: CollectionType {
let title: String
var elements: [T]
var startIndex: Int { return 0 }
var endIndex: Int { return elements.count }
subscript(index: Int) -> T? { … }
func generate() -> ArrayGenerator<T> { … }
}
struct Section<T>: CollectionType {
let title: String
var elements: [T]
var startIndex: Int { return 0 }
var endIndex: Int { return elements.count }
subscript(index: Int) -> T {
return elements[index]
}
func generate() -> ArrayGenerator<T> { … }
}
struct Section<T>: CollectionType {
let title: String
let elements: [T]
var startIndex: Int { return 0 }
var endIndex: Int { return elements.count }
subscript(index: Int) -> T {
return elements[index]
}
subscript(safe index: Int) -> T? {
return elements[safe: index]
}
func generate() -> ArrayGenerator<T> { … }
}
let cars = ["911", "Cayman", "Cayenne"]
let section = Section(title: "Porsche", elements: cars)
section.count
// 3
section.first
// Optional("911")
section.isEmpty
// false
section.indexOf("Cayman")
// 1
Epilogue
So dictionaries aren’t Collections?
struct Dictionary<K : Hashable, V> {
subscript(key: K) -> V?
subscript(position: DictionaryIndex<K, V>) -> (K, V)
}
let dic = ["a": "audi", "b": "bmw", "c": "citroen"]
let index = dic.startIndex
// DictionaryIndex<String, String>
dic[index]
// ("a", "audi")
dic[index.advancedBy(1)]
// ("b", "bmw")
dic[index.advancedBy(3)]
// Fatal error
Thank you! 🤗
@greg3z 🤔
medium.com/swift-programming

Swift Sequences & Collections