Andrew
Andrew

Reputation: 43153

Array without function in Swift

Following the guides on generics and type constraints, I attempted to create an Array.without function as follows:

extension Array {
  func without<T: Equatable>(item:T) -> T[] {
    return self.map { $0 != item }
  }
}

Testing this in a playground, I can't get it to work as the != value triggers a compiler error, "Could not find an overload for != that accepts the supplied arguments".

I believe the <T: Equatable> should be enough to allow the use of != but obviously it didn't work. What's missing here?

Upvotes: 3

Views: 154

Answers (1)

drewag
drewag

Reputation: 94803

The problem is that the T you define in the method has nothing to do with the T defined in the actual struct. Your local T is constrained to be Equatable, but the Array version of T is still not constrained and that is what self.map is providing to the closure. The closure is getting an Array type T and you are trying to compare that to your local T which isn't necessarily the same type.

I think the best you can do is something like this:

extension Array {
    func without<U : Equatable>(item : U) -> [T]  {
        return self.filter { $0 as? U != item }
    }
}

Unfortunately, this will still work if you call it with an instance of a different type as is stored in the array. If you do, it will simply return the original Array. It will not let you call it with an instance that is not equatable though.

Notes:

  1. I used filter instead of map because that is the method that allows you to filter out contents of an array. map is for changing contents
  2. I changed without to return an array. filter and map do not modify the array, instead they return a new version of the array that is altered according to the closure.

Upvotes: 2

Related Questions