Let's assume I have an a collection that holds either type A
or type B
then I think it's quite a natural thing to want a lazy collection of only the A
values and one for only the B
values.
For example:
struct ABCollection<A, B> {
fileprivate let elements: [AB]
enum AB {
case a(A)
case b(B)
}
typealias LazyACollection = LazyMapCollection<LazyFilterCollection<[AB]>, A>
var onlyAs: LazyACollection {
return self.elements.lazy.filter {
switch $0 {
case .a:
return true
case .b:
return false
}
}.map { (input: AB) -> A in
switch input {
case .a(let value):
return value
case .b:
fatalError()
}
}
}
}
extension ABCollection: Collection {
typealias Element = AB
typealias Iterator = Array<AB>.Iterator
var startIndex : Int {
return self.elements.startIndex
}
var endIndex : Int {
return self.elements.endIndex
}
func index(after i: Int) -> Int {
return self.elements.index(after: i)
}
subscript(position : Int) -> AB {
return self.elements[position]
}
func makeIterator() -> IndexingIterator<Array<AB>> {
return self.elements.makeIterator()
}
}
but the onlyAs
is quite ugly for two reasons:
- the type:
LazyMapCollection<LazyFilterCollection<[AB]>, A>
- the implementation contains a
fatalError()
because there can't be any.b(B)
values left (as we filtered them out)
sure, with the new compactMap
I could write this much neater:
var onlyAsBetter: LazyCompactMapCollection<[AB], A> {
return self.elements.lazy.compactMap {
switch $0 {
case .a(let a):
return a
case .b:
return nil
}
}
}
except, that LazyCompactMapCollection
doesn't exist . I think this should be added. Incidentally
LazyCompactMapCollection
is a more general version of LazyFilterCollection
and LazyMapCollection
and could replace them both, we might however not want to do that for performance reasons.
Please let me know what you think.
Thanks,
Johannes