Reputation: 20815
I'm attempting to use the contains
function in swift to see if my objects is in a typed array but I'm getting:
Cannot invoke 'contains' with an argument list of Type '([Foo], Foo)'
class Foo {
}
let foo = Foo()
let foos = [Foo(), Foo()]
contains(foos, foo)
Why is this happening?
I've implemented the ==
function but I still get the same error. Am I doing this improperly?
class Foo {}
func ==(lhs: Foo, rhs: Foo) -> Bool {
return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
}
let foo = Foo()
let foos = [Foo(), Foo()]
contains(foos, foo)
Upvotes: 2
Views: 4702
Reputation: 13316
Also note that there is always a way to check for an instance of a class in an array, even if you haven't implemented the equatable protocol or inherited from NSObject
. You can use reduce
to do it like this:
class MyClass { }
let myClass1 = MyClass()
let myArray = [myClass1]
let lookForMyClass1 = myArray.reduce(false) { $0 || $1 === myClass1 }
println(lookForMyClass1) // Outputs: true
And you can generalize that to look for any class object in any SequenceType
by overloading contains
with something like this:
func contains<T: AnyObject, S: SequenceType where T == S.Generator.Element>(#haystack: S, #needle: T) -> Bool {
return reduce(haystack, false) { $0 || $1 === needle }
}
Now you can call contains
like this:
let searchForMyClass1 = contains(haystack: myArray, needle: myClass1)
println(searchForMyClass1) // Output: true
Upvotes: 0
Reputation: 108111
Classes don't automatically inherit any equality logic from the base classs, so you need to be explicit and have Foo
to conform to the Equatable
protocol.
Actually, the only sensible equality the compiler could derive from that class declaration is the identity, and you probably don't want that.
Please note that
class Foo {}
is not the same as
class Foo : NSObject { }
By inheriting from NSObject
you also inherit the default implementation of isEqual
, which provides object identity equality.
Concerning your last update, you're only missing the Equatable
protocol in the class definition. The following compiles just fine
class Foo : Equatable {}
func ==(lhs: Foo, rhs: Foo) -> Bool {
return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
// or simply
// return lhs === rhs
}
let foo = Foo()
let foos = [Foo(), Foo()]
contains(foos, foo)
Or simply inherit from NSObject
, which already provides identity equality
class Foo : NSObject {}
let foo = Foo()
let foos = [Foo(), Foo()]
contains(foos, foo)
Upvotes: 5
Reputation: 299345
The only function signature for contains
is:
func contains<S : SequenceType where S.Generator.Element : Equatable>(seq: S, x: S.Generator.Element) -> Bool
Foo
is not Equatable
, so it doesn't match this signature.
Upvotes: 2