Hi Zhao Thanks for your response.
I understand your point, but when using third party classes I don’t know if the hash values are comparable, but for example I may want to have a set of ‘data' (NSData) and a subset of ‘mutable data' (NSMutableData), which point to the same objects. As a user of swift I would expect to be able to subtract Set<NSMutableData> from Set<NSData>. Your last example perhaps works in Swift 3, so this may be fixed now, but in Swift 2 you get the error Cannot invoke 'subtract' with an argument list of type '(Set<Bar>)’ Perhaps Swift 3 supports it with some additional safety around hashValue overriding or something. Thanks Nick > On 1 Sep 2016, at 04:00, Zhao Xin <owe...@gmail.com> wrote: > > I don't see the point. For example if an element in Set<B> and another > element in Set<A> are with a same hash value. Neither of the elements should > be subtracted. As they are in different types. And hash values between > different types are not guaranteed to be comparable. > > import Foundation > > class Foo:Hashable { > var value: Int > > public var hashValue: Int { > return value > } > > public static func ==(lhs: Foo, rhs: Foo) -> Bool { > return lhs.value == rhs.value > } > > required init(_ value:Int) { > self.value = value > } > } > > class Bar:Foo { > override public var hashValue: Int { > return value * 10 > } > } > > let foo = Foo(10) > let bar = Bar(10) > > print(foo.hashValue) // 10 > print(bar.hashValue) // 100 > print((bar as Foo).hashValue) // 100 instead of 10 > > print(foo == bar) // true > print(foo.hashValue == bar.hashValue) // false > > As you can see in the above code, although `foo == bar` is true, > `foo.hashValue == bar.hashValue` is not guaranteed to be true. As far as I > know, Set<T> uses hash values instead of equations to compare the elements. > So the results of a super class and its sub class are not guaranteed. Also, > as `(bar as Foo).hashValue` is always the result of its own class, you can't > get the results you want through casting. > > var fooSet:Set<Foo> = [Foo(10), Foo(9), Foo(8), Foo(7)] > var barSet:Set<Bar> = [Bar(8), Bar(7), Bar(6), Bar(5)] > > fooSet.subtract(barSet) > fooSet.forEach { print("\(type(of:$0)), value:\($0.value)") } > /* > Foo, value:10 > Foo, value:9 > Foo, value:8 // Here is a mystery, Foo(7) is unreasonably missing. > */ > > However, if you can guarantee the hash values are comparable, you still can > get the results you want. > > class Foo:Hashable { > var value: Int > > public var hashValue: Int { > return value > } > > public static func ==(lhs: Foo, rhs: Foo) -> Bool { > return lhs.value == rhs.value > } > > required init(_ value:Int) { > self.value = value > } > } > > class Bar:Foo { > var name = "bar" > } > > var fooSet:Set<Foo> = [Foo(10), Foo(9), Foo(8), Foo(7)] > var barSet:Set<Bar> = [Bar(8), Bar(7), Bar(6), Bar(5)] > > fooSet.subtract(barSet) > fooSet.forEach { print("\(type(of:$0)), value:\($0.value)") } > /* > Foo, value:10 > Foo, value:9 > */ > > > Zhaoxin > > On Thu, Sep 1, 2016 at 8:31 AM, Nick Brook via swift-users > <swift-users@swift.org <mailto:swift-users@swift.org>> wrote: > I have a set, Set<A> and a subset of that, Set<B>, where B: A. I want to > subtract Set<B> from Set<A>, but the subtract function signature specifies > that the set elements must be the same type (S.Generator.Element == Element). > I guess this is because Element is not required to be a class, simply > hashable, therefore inheritance is not guaranteed? Is there any way this > could be implemented in Set, in an extension, or what would be the most > efficient way to perform that operation? > > Thanks > > Nick > > _______________________________________________ > swift-users mailing list > swift-users@swift.org <mailto:swift-users@swift.org> > https://lists.swift.org/mailman/listinfo/swift-users > <https://lists.swift.org/mailman/listinfo/swift-users> > >
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users