Realm
July 07, 2016
8.2k

# Brandon Kase: Grokking Lazy Sequences and Collections

July 07, 2016

## Transcript

4. ### PROBLEMS There are a lot of photos Loading a photo's

data is expensive

is expensive

10. ### HOLDING THINGS let fetchresult = PHAsset.fetchAllAssets/*...*/() var arr = [PHAsset]()

fetchresult.enumerateAssetsUsingBlock { obj, /*...*/ arr.append(obj as! PHAsset) }
11. ### HOLDING THINGS let fetchresult = PHAsset.fetchAllAssets/*...*/() var arr = [PHAsset]()

fetchresult.enumerateAssetsUsingBlock { obj, /*...*/ arr.append(obj as! PHAsset) } // slowwwwww

13. ### GROUPS OF THINGS A Collection is an Indexable Sequence A

Sequence is an Iterator maker An Iterator can produce one or more Elements

Element? }
15. ### ITERATORPROTOCOL Let's say we want to iterate over the even

numbers https://i.ytimg.com/vi/A9NfHIIwNN4/maxresdefault.jpg
16. ### ITERATORPROTOCOL struct Evens: IteratorProtocol { var state: Int = 0

mutating func next() -> Int? { let curr = state state += 2 return .some(curr) } }
17. ### ITERATORPROTOCOL let s = Evens() for _ in 1...5 {

print(s.next()!) // 0, 2, 4, 6, 8 }

4, 6, 8 }

22. ### SEQUENCE extension Sequence where Iterator == Self, Self: IteratorProtocol {

func makeIterator() -> Iterator { return self } }

26. ### SEQUENCE must be able to produce an iterator could be

one-pass or multipass could be finite or infinite

30. ### COLLECTION struct PhotosMetadata: Collection { /*...*/ var startIndex: Int {

/*...*/ } var endIndex: Int { /*...*/ } func index(after i: Int) -> Int { /*...*/ } subscript(i: Int) -> PHAsset { /*...*/ } }
31. ### COLLECTION Why do we need to deal with the index

crap? struct PhotosMetadata: Collection { /*...*/ var startIndex: Int { /*...*/ } var endIndex: Int { /*...*/ } func index(after i: Int) -> Int { /*...*/ } subscript(i: Int) -> PHAsset { /*...*/ } }
32. ### COLLECTION RULES has addressable positions (index) must support multipass iteration

exists a one-to-one mapping of indices to elements No infinite structures! expect O(1) subscript access

= base }

+ 1 }

}

} // slowwww

46. ### LAZY GROUPS OF THINGS Transformations computed when the information is

forced out https://media.giphy.com/media/AyXMnDH4nA7jW/giphy.gif

// [2, 3, 4]
50. ### LAZYSEQUENCE MAP Evens().lazy.map{ \$0 + 1 } // LazyMapSequence<Int, Int>

// nothing is computed yet!
51. ### LAZYCOLLECTION MAP [1,2,3].lazy.map{ \$0 + 1 } // LazyMapRandomAccessCollection<Int, Int>

// nothing is computed yet!

53. ### H O W C A N A N O V

E R R I D E N M E T H O D R E T U R N D I F F E R E N T T Y P E S ?

55. ### DEFAULT IMPLEMENTATIONS protocol A { } extension A { func

woo() -> Self { return self } func hi() -> String { return "A" } }

57. ### DEFAULT IMPLEMENTATIONS protocol B { } extension B { func

hi() -> Int { return 0 } }
58. ### DEFAULT IMPLEMENTATIONS struct Mystery: A, B { } print(Mystery().woo().hi()) //

compile error!
59. ### DEFAULT IMPLEMENTATIONS // now B subsumes A protocol B: A

{ } extension B { func hi() -> Int { return 0 } }
60. ### DEFAULT IMPLEMENTATIONS struct Mystery: B { } print(Mystery().woo().hi()) // 0

// NOT a compile error!
61. ### MAPS Evens().lazy.map{ \$0 + 1 } // LazyMapSequence<Int, Int> //

nothing is computed yet!

63. ### LAZYMAPSEQUENCE struct LazyMapSequence<S: Sequence>: LazySequenceProtocol { func makeIterator() -> LazyMapIterator</*...*/>

{ /*...*/ } }

65. ### LAZYMAPITERATOR struct LazyMapIterator<Base: Iterator, Element>: IteratorProtocol, Sequence { var _base:

Base let _transform: (Base.Element) -> Element }
66. ### LAZYMAPITERATOR struct LazyMapIterator<Base: Iterator, Element>: IteratorProtocol, Sequence { var _base:

Base let _transform: (Base.Element) -> Element mutating func next() -> Element? { return _base.next().map(_transform) } }

68. ### BURRITOS let a = [1,2,3].lazy.map{ \$0 + 1 }.filter{ \$0

!= 3 } // a: LazyFilterBidirectionalCollection< // LazyMapRandomAccessCollection< // Array<Int>, Int // > // >
69. ### BURRITOS http://images.wisegeek.com/flour-tortilla.jpg

} // not slow!
71. ### PHOTOS func prepareData(d: PhotosMetadata) -> ? { return d.lazy .filter{

\$0.isPhoto() } // skip videos .map{ Photo(url: \$0.url) } // make photos .map{ PhotoView(photo: \$0) } // make view }

76. ### TYPE ERASURE let m = AnyCollection( d.lazy.filter{}.map{}/*...*/ ) // m:

AnyCollection<PhotoView>

80. ### NEW TORTILLAS let a = [1,2,3,4] for x in a.lazy.everyOther()

{ print(x) // 2,4 }
81. ### NEW TORTILLAS // the tortilla sequence struct LazyEveryOtherSequence <S: Sequence>:

LazySequenceProtocol { var base: S func makeIterator() -> LazyEveryOtherIterator<S.Iterator> { return LazyEveryOtherIterator(base: base.makeIterator()) } }
82. ### NEW TORTILLAS struct LazyEveryOtherIterator <I: IteratorProtocol>: IteratorProtocol { var base:

I mutating func next() -> I.Element? { if let _ = base.next() { return base.next() } else { return nil } } }
83. ### NEW TORTILLAS extension LazySequenceProtocol { func everyOther() -> LazyEveryOtherSequence<Self> {

return LazyEveryOtherSequence(base: self) } }

89. ### RECAP Collections hold our photo metadata and photos LazyCollection's map

transforms our data
90. ### RECAP Collections hold our photo metadata and photos LazyCollection's map

transforms our data AnyCollection gives maintainable type signatures
91. ### RECAP Collections hold our photo metadata and photos LazyCollection's map

transforms our data AnyCollection gives maintainable type signatures We can create new operators that compose

93. ### P.S. IBM Swift Sandbox is legit Check out Unary indexed

collections in appendix

always
97. ### EAGER class A { var eagerField: Int = 1 +

1 /* ... */ }
98. ### LAZY class A { lazy var lazyField: Int = 1

+ 1 /* ... */ }

100. ### EAGER GROUPS OF THINGS Eager means operations on the groups

of things are eager The groups of things themselves can be strict or lazy

102. ### UNARY let u: Unary</*...*/> u[""] // 1st element u["x"] //

2st element u["xx"] // 3st element u["xxx"] // 4st element

== Int {
108. ### UNARY { var startIndex: String { /*...*/ } var endIndex:

String { /*...*/ } func index(after i: String) -> String { /*...*/ } subscript(i: String) -> C.Iterator.Element { /*...*/ } }

= xs }

_ in "x"}) }

+ "x" }

114. ### UNARY let u: Unary<Array<Int>> = Unary([1, 2, 3, 4, 5,

6]) print(u.lazy.map{ x in x + 1 }["xxx"])
115. ### COLLECTION-INDEX VARIANTS How can you move to the next index?

Collection (ForwardDirection) Go forward in O(1) BidirectionalCollection Go forward or backward in O(1) RandomAccessCollection Get the difference between two indices in O(1)

117. ### TYPE ERASURE Type erasure works by moving the type info

to the constructor
118. ### TYPE ERASURE // one of the inits for AnySequence init<S

: Sequence where S.Iterator.Element == Element, S.SubSequence : Sequence, S.SubSequence.Iterator.Element == Element, S.SubSequence.SubSequence == S.SubSequence>(_ base: S)