[Pitch] Set of AnyObject by reference


(Guoye Zhang) #1

I'm building an document-based app, and I'm having a problem regarding to Set.

What I hope to achieve is to have a Set of unique objects by their references. For example, I might put in two rectangles with the same height and width (which makes them equal, but they are still different instances). Currently, I have two solutions:

Option 1:
Inherit from NSObject

class Rectangle: NSObject {
   var height, width: Int
   func isEqualByValue(_ other: Rectangle) -> Bool {
     return height == other.height && width == other.width
   }
}

Set<Rectangle> meets my requirements, but it drags a lot of baggage from Objective-C, also makes comparing by value ugly.

Option 2:
Wrap them

struct RectangleReference: Hashable {
   let value: Rectangle
   var hashValue: Int {
     return unsafeAddress(of: value).hashValue // This might be removed in Swift 3 (SR-1957)
   }
}
func ==(lhs: RectangleReference, rhs: RectangleReference) -> Bool {
   return lhs.value === rhs.value
}

Set<RectangleReference> works fine, but it has unsafeAddress(of:) which is unsafe and might be removed in Swift 3.

What I'd like to use is a ReferenceSet<Element: AnyObject> which compares objects by their references. Any reference typed instances can be put in it without confirming to Hashable protocol. ReferenceDictionary<Key: AnyObject, Value> is also welcomed.

Any opinions?

- Guoye Zhang


(Dmitri Gribenko) #2

Try this:

public final class ReferenceEqualityBox<Wrapped : Equatable> : Hashable {
  public var value: Wrapped
  public init(_ value: Wrapped) {
    self.value = value
  }
  public var hashValue: Int {
    return ObjectIdentifier(self).hashValue
  }
}
public func == <Wrapped> (
  lhs: ReferenceEqualityBox<Wrapped>,
  rhs: ReferenceEqualityBox<Wrapped>
) -> Bool {
  return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
}

Dmitri

···

On Sun, Jul 17, 2016 at 2:00 AM, 张国晔 via swift-evolution <swift-evolution@swift.org> wrote:

I'm building an document-based app, and I'm having a problem regarding to Set.

What I hope to achieve is to have a Set of unique objects by their references.

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/


(Tino) #3

What I hope to achieve is to have a Set of unique objects by their references. For example, I might put in two rectangles with the same height and width (which makes them equal, but they are still different instances).

I guess this is not the best place for such problems, but did you already look at ObjectIdentifier?

Tino


(Guoye Zhang) #4

在 2016年7月17日,17:44,Tino Heth <2th@gmx.de> 写道:

What I hope to achieve is to have a Set of unique objects by their references. For example, I might put in two rectangles with the same height and width (which makes them equal, but they are still different instances).

I guess this is not the best place for such problems, but did you already look at ObjectIdentifier?

Tino

The problem is the motivation for my proposal of adding ReferenceSet<Element: AnyObject> and ReferenceDictionary<Key: AnyObject, Value> to stdlib.

The original object cannot be retrieved from ObjectIdentifier, which makes it unsuitable for my use-case.

- Guoye Zhang


(Guoye Zhang) #5

在 2016年7月18日,02:08,Dmitri Gribenko <gribozavr@gmail.com> 写道:

I'm building an document-based app, and I'm having a problem regarding to Set.

What I hope to achieve is to have a Set of unique objects by their references.

Try this:

public final class ReferenceEqualityBox<Wrapped : Equatable> : Hashable {
public var value: Wrapped
public init(_ value: Wrapped) {
   self.value = value
}
public var hashValue: Int {
   return ObjectIdentifier(self).hashValue
}
}
public func == <Wrapped> (
lhs: ReferenceEqualityBox<Wrapped>,
rhs: ReferenceEqualityBox<Wrapped>
) -> Bool {
return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
}

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

Thanks, I haven't thought of using ObjectIdentifier instead of unsafeAddress(of:). That's a lot better than my option 2.

- Guoye Zhang

···

On Sun, Jul 17, 2016 at 2:00 AM, 张国晔 via swift-evolution > <swift-evolution@swift.org> wrote: