Is there a way to make a generic extension to a protocol?
As an example take a filterNils method, that removes all nil elements from a collection and unwraps the rest:
extension CollectionType where Generator.Element == Optional<AnyObject> {
func filterNils() -> [AnyObject] {
return self.filter { $0 != nil }.map { $0! }
}
}
This code snippet only works for variables of type Array<AnyObject?> though, not for e.g. Array<Int?>.
What I really want to achieve would be along the lines of this:
extension CollectionType where Generator.Element == Optional<T> {
func filterNils() -> [T] {
return self.filter { $0 != nil }.map { $0! }
}
}
But that is not valid Swift 2.0 code. Any suggestions how that can be achieved without using parameter generics like in this solution [2]?
The challenge is that Optionals don't conform to a particular protocol. That can be solved by creating a new OptionalType protocol that declares flatMap and extending Optional for conformance:
protocol OptionalType {
typealias T
func flatMap<U>(@noescape f: (T) -> U?) -> U?
}
extension Optional : OptionalType { }
Then you can add an extension to Array (or better, SequenceType):
extension SequenceType where Generator.Element: OptionalType {
func flatten() -> [Generator.Element.T] {
return self.map { $0.flatMap { $0 } }
.filter { $0 != nil }
.map { $0! }
}
}
let mixed: [Int?] = [1, 2, nil, 3, nil, 4]
let numbers = mixed.flatten() // 1, 2, 3, 4