0

I have places where I have both Set and Array of MyType.

In these places, I need to filter down my Sequences, and you'll notice that the filter block is the same for both Sequence types.

Is there any way I can implement a generic Sequence extension, where the filterFor method will return the correct type (Set or Array), depending on the receiver?

extension Set where Element: MyType {
    func filterFor(valueToMatch:String) -> Set<MyType> {
        return self.filter{
            $0.myProperty.caseInsensitiveCompare(valueToMatch) == .orderedSame
        }
    }
}

extension Array where Element: MyType {
    func filterFor(valueToMatch:String) -> [MyType] {
        return self.filter{
            $0.myProperty.caseInsensitiveCompare(valueToMatch) == .orderedSame
        }
    }
}
A O
  • 5,516
  • 3
  • 33
  • 68

1 Answers1

1

Unfortunately, no. Set has two overloads of filter(_:), with these types:

  1. func filter(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> [Self.Element]
  2. func filter(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> Set<Self.Element>

The first is the implementation that satisfies the requirements of conformance to Sequence. The latter is just a method that Set implements, that isn't tied to any protocol.

There is no generic way to reference a variant of Filter that returns anything besides Array<Self.Element>. There is a Swift Evolution proposal to fix this (SE-0174 - Change filter to return an associated type). It has been accepted, but has not been implemented yet.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • Makes sense, thanks for digging up the links for me, I'll deal with the two implementations for now then :) – A O Oct 30 '18 at 01:06