5

I am trying to extend Swift's Array class with the following func:

func containsObjectIdenticalTo(obj: T) -> Bool {
    // objectPassingTest returns the first object passing the test
    return objectPassingTest { x in x == obj }
}

Apparently, this won't compile as the compiler doesn't know yet if == is implemented for type T. I then change the code to this

func containsObjectIdenticalTo(obj: T) -> Bool {
    return objectPassingTest {
        x in
        assert(x is Equatable && obj is Equatable)
        return (x as Equatable) == (obj as Equatable)
    } != nil
}

Which doesn't work either, since conformance against Equatable can't be checked (because Equatable wasn't defined with @obj) !

Any thoughts on this? Would be nice if there's some way to assert directly if T conforms to Equatable, but I haven't read that anywhere. Swift seems to be less dynamic than Obj-C in these stuffs.

UPDATE: Tried this suggestion and it doesn't work (don't know exactly what <T: Equatable> is for, tho it does compile).

func containsObjectIdenticalTo<T: Equatable>(obj: T) -> Bool {
    var x = self[0]
    var y = self[0]
    return x == y // Error here
}
Khanh Nguyen
  • 11,112
  • 10
  • 52
  • 65

4 Answers4

4

Specify that T must be equatable in the Method's signature:

func containsObjectIdenticalTo<T: Equatable>(obj: T) -> Bool {/*...*/}
Connor Pearson
  • 63,902
  • 28
  • 145
  • 142
  • It looks nice, but doesn't work. Please see my updates. – Khanh Nguyen Jun 12 '14 at 00:41
  • 1
    @KhanhNguyen That's because you make sure the parameter is equatable but the elements in the array may not be. This answer should solve your overall problem though: http://stackoverflow.com/a/24091318/754604 – Connor Pearson Jun 12 '14 at 01:02
2

i got this from ExSwift : https://github.com/pNre/ExSwift

 func contains <T: Equatable> (items: T...) -> Bool {
        return items.all { self.indexOf($0) >= 0 }
    }

func indexOf <U: Equatable> (item: U) -> Int? {
        if item is Element {
            if let found = find(reinterpretCast(self) as Array<U>, item) {
                return found
            }

            return nil
        }

        return nil
    }

func all (call: (Element) -> Bool) -> Bool {
        for item in self {
            if !call(item) {
                return false
            }
        }

        return true
    }

maybe you can try it

guoleii
  • 496
  • 6
  • 15
1

How about:

func containsObjectIdenticalTo<T : Equatable>(obj: T) -> Bool {
 ... etc ...
}
Eduardo
  • 8,362
  • 6
  • 38
  • 72
1

In the end, I resorted to this solution

func containsObjectIdenticalTo<U: Equatable>(obj: U) -> Bool {
    return objectPassingTest({
        x in
        return x as U == obj
    }) != nil
}

Might not be the best (ie safest) one. But it works great.

Khanh Nguyen
  • 11,112
  • 10
  • 52
  • 65