Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Array.insert generics

func getIndex<T: Equatable>(valueToFind: T) -> Int? {...}

mutating func replaceObjectWithObject<T: Equatable>(obj1: T, obj2: T) {
    if let index = self.getIndex(obj1) {
        self.removeAtIndex(index)
        self.insert(obj2, atIndex: index)           // Error here: 'T' is not convertible to 'T'
    }
}

I have that function which is suppose to replace an element with another element. But Im not very familiar with Generics and don't know why this is not working. Please help.

If I remove the Equatable from the mutating func the error message jumps to the first line in that func and if I then replace that with the func find() that gives me the same error as on line 3.

like image 808
Arbitur Avatar asked Sep 30 '22 23:09

Arbitur


1 Answers

This is actually not possible via an extension under the existing system of protocols and generics in Swift - you can't add additional constraints to the generic subtype of a type, so you can't extend Array with a method that requires that its contents conform to Equatable.

You can see this restriction in action with the built-in Array type -- there's no myArray.find(element) method, but there is a global function find() that takes a collection and an element, with a generic constraint that the collection's elements are Equatable:

func find<C : CollectionType where C.Generator.Element : Equatable>(domain: C, value: C.Generator.Element) -> C.Index?

You can do this for your method - you just need to write a similar top-level function:

func replaceObjectWithObject<C : RangeReplaceableCollectionType where C.Generator.Element : Equatable>(inout collection: C, obj1: C.Generator.Element, obj2: C.Generator.Element) {
    if let index = find(collection, obj1) {
        removeAtIndex(&collection, index)
        insert(&collection, obj2, atIndex: index)
    }
}

var myArray = [1, 2, 3, 4, 5]
replaceObjectWithObject(&myArray, 2, 7)
// 1, 2, 7, 4, 5
like image 192
Nate Cook Avatar answered Nov 15 '22 10:11

Nate Cook