Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 5.0 "Set" allowing duplicate values

In a Swift 5.0 Playground, I was experimenting with extensions on CGPoint such that it treated points as integer values in terms of hashing and equality.

To my surprise, even after overriding hash() and == on CGPoint, a Set of CGPoints still held similar values as independent points even though two elements should have collided and kept only one. Is there some other method you would need to override on CGPoint to have this work as expected?

P.S. Probably best not to do this in practice as it might affect the system, better to provide some kind of wrapper to manage equality. But I would like to know why this does not work.

The Playground contents along with results given after execution:

// Extension to treat points as integer values (not reccomended approach)
extension CGPoint : Hashable {
    public func hash(into hasher: inout Hasher) {
                hasher.combine(Int(x))
        hasher.combine(Int(y))
    }

    static public func == (lhs: CGPoint, rhs: CGPoint) -> Bool {
        return Int(lhs.x) == Int(rhs.x) && Int(lhs.y) == Int(rhs.y)
    }
}

var pSet : Set<CGPoint> = []

let p1 = CGPoint.zero
let p2 =  CGPoint(x: 20.1, y: 30)
let p3 =  CGPoint(x:20, y: 30)

pSet.insert(p1) // inserted true
pSet.insert(p2) // inserted true
pSet.insert(p3) // inserted true(!), should be false

p2 == p3 // true

pSet.count // 3(!), should be two
p2.hashValue  // Same as p3
p3.hashValue  // Same as p2

pSet // shows all three values, all points defined, should be two values only
like image 219
Kendall Helmstetter Gelner Avatar asked Aug 31 '25 01:08

Kendall Helmstetter Gelner


1 Answers

rmaddy and Martin R identified the problem, but here it is as an answer: Set doesn't use your == function. It uses the == function defined in the standard library, because Set is defined in the standard library. You can prove this by calling print is your == function. When you insert a point into Set, you will see that your print doesn't run.

like image 51
rob mayoff Avatar answered Sep 03 '25 03:09

rob mayoff