Swift Sequences & Collections

Post on 15-Apr-2017

5,484 views 0 download

transcript

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