Reputation: 69777
This works:
func removeObject<T : Equatable>(object: T, array: [T]) -> Array<T>
{
return array.filter() { $0 != object }
}
let threeThings = ["one", "two", "three"]
twoThings = removeObject("three", threeThings)
However, I'd like to check for inequality with this !==
. Then I get error "Type 'T' does not conform to protocol 'AnyObject'"
How can this code be fixed? (I've see the code here but I'd like to learn how to use filter properly).
Upvotes: 0
Views: 352
Reputation: 13316
!==
checks for "identity", not "equality". Identity is a property of reference types which all support the AnyObject
protocol, and it means that the two variables that you are comparing point to the same actual object, and not just another object with the same value.
That means you can't use ===
or !==
with normal value types, like strings, integers, arrays, etc.
Try typing this into a playground:
let a = "yes"
let b = a
println(a === b)
You should get a message saying that String
doesn't conform to the AnyObject
protocol, because String is a value type (a struct) and doesn't support AnyObject
, so you can't use ===
with it.
You can use ===
with any instance of a class, because classes are reference types, not value types.
You could put a constraint on T requiring that it conform to AnyObject
.
func removeObject<T : Equatable where T: AnyObject>...
It should work, then, for reference types (including all class instances). But then your function won't work for value types (which include all structs).
Why do you need to check for identity (===
) instead of equality (==
)?
Upvotes: 1
Reputation: 535547
If you want to use !==
instead of !=
, then, instead of the type constraint <T : Equatable>
say <T : AnyObject>
. All you have to do is listen to what the error message is telling you!
Note that this has nothing to do with using the filter function. It is simply a matter of types. You cannot use a method with an object of a type for which that method is not implemented. !==
is implemented for AnyObject so if you want to use it you must guarantee to the compiler that this type will be an AnyObject. That is what the type constraint does.
Upvotes: 2
Reputation: 539945
The identical operator ===
and its negation !==
are only defined for
instances of classes, i.e. instances of AnyObject
:
func removeObject<T : AnyObject>(object: T, array: [T]) -> Array<T>
{
return array.filter() { $0 !== object }
}
===
checks if two variables refer to the same single instance.
Note that your code
let threeThings = ["one", "two", "three"]
twoThings = removeObject("three", threeThings)
does still compile and run, but gives the (perhaps unexpected) result
[one, two, three]
The Swift strings (which are value types and not class types) are automatically
bridged to NSString
, and the two instances of NSString
representing "three"
need not be the same.
Upvotes: 3