Hi,
I just wanted to share a bit of code I use. Swift does not allow Sets of protocols, so I just wrote my own SetOfProtocol<T> structure. T should be a protocol that adopts HashableProtocol : this is not enforced by the compiler since XCode won't check (yet?) that a non concrete type adopts a protocol.
Please comment and report bugs !
import Swift
public protocol HashableProtocol {
func isEqualTo(other: HashableProtocol) -> Bool
var hashValue: Int {get}
}
extension HashableProtocol where Self: Equatable {
public func isEqualTo(other: HashableProtocol) -> Bool {
if let o = other as? Self {
return self == o
}
return false
}
}
private struct Wrapper<T>: Hashable {
var _value: HashableProtocol
var value: T {return _value as! T}
var hashValue: Int {
return _value.hashValue
}
init(_ reference: T) {
self._value = reference as! HashableProtocol
}
}
private func == <T> (left: Wrapper<T>, right: Wrapper<T>) -> Bool{
return left._value.isEqualTo(right._value)
}
public struct SetOfProtocolIndex<T>: ForwardIndexType, Comparable {
private var index: SetIndex<Wrapper<T>>
public typealias Distance = SetIndex<Wrapper<T>>.Distance
@warn_unused_result
public func advancedBy(n: SetOfProtocolIndex.Distance) -> SetOfProtocolIndex {
return SetOfProtocolIndex<T>(index: index.advancedBy(n))
}
@warn_unused_result
public func advancedBy(n: SetOfProtocolIndex.Distance, limit: SetOfProtocolIndex) -> SetOfProtocolIndex {
return SetOfProtocolIndex<T>(index: index.advancedBy(n, limit: limit.index))
}
@warn_unused_result
public func distanceTo(end: SetOfProtocolIndex) -> SetOfProtocolIndex.Distance {
return index.distanceTo(end.index)
}
@warn_unused_result
public func successor() -> SetOfProtocolIndex {
return SetOfProtocolIndex<T>(index: index.successor())
}
}
@warn_unused_result
public func == <T> (lhs: SetOfProtocolIndex<T>, rhs: SetOfProtocolIndex<T>) -> Bool {
return lhs.index == rhs.index
}
@warn_unused_result
public func < <T> (lhs: SetOfProtocolIndex<T>, rhs: SetOfProtocolIndex<T>) -> Bool {
return lhs.index < rhs.index
}
@warn_unused_result
public func <= <T> (lhs: SetOfProtocolIndex<T>, rhs: SetOfProtocolIndex<T>) -> Bool {
return lhs.index <= rhs.index
}
@warn_unused_result
public func >= <T> (lhs: SetOfProtocolIndex<T>, rhs: SetOfProtocolIndex<T>) -> Bool {
return lhs.index >= rhs.index
}
@warn_unused_result
public func > <T> (lhs: SetOfProtocolIndex<T>, rhs: SetOfProtocolIndex<T>) -> Bool {
return lhs.index > rhs.index
}
public struct SetOfProtocol<T>: CollectionType, Equatable, ArrayLiteralConvertible {
private var set: Set<Wrapper<T>>
public init(minimumCapacity: Int) {
set = Set<Wrapper<T>>(minimumCapacity: minimumCapacity)
}
public var startIndex: SetOfProtocolIndex<T> {return SetOfProtocolIndex(index: set.startIndex)}
public var endIndex: SetOfProtocolIndex<T> {return SetOfProtocolIndex(index: set.endIndex)}
@warn_unused_result
public func contains(member: T) -> Bool {return set.contains(Wrapper(member))}
@warn_unused_result
public func indexOf(member: T) -> SetOfProtocolIndex<T>? {
guard let index = set.indexOf(Wrapper(member)) else {return nil}
return SetOfProtocolIndex(index: index)
}
public mutating func insert(member: T) {set.insert(Wrapper(member))}
public mutating func remove(member: T) -> T? {return set.remove(Wrapper(member))?.value}
public mutating func removeAtIndex(index: SetOfProtocolIndex<T>) -> T {return set.removeAtIndex(index.index).value}
public mutating func removeAll(keepCapacity keepCapacity: Bool = false) {set.removeAll(keepCapacity: keepCapacity)}
public mutating func removeFirst() -> T {return set.removeFirst().value}
public var count: Int {return set.count}
public subscript (position: SetOfProtocolIndex<T>) -> T {return set[position.index].value}
public func generate() -> AnyGenerator<T> {
var generator: SetGenerator<Wrapper<T>>? = set.generate()
return anyGenerator {generator?.next()?.value}
}
public init(arrayLiteral elements: T...) {
set = Set()
for member in elements {
set.insert(Wrapper(member))
}
}
public init() {
set = Set<Wrapper<T>>()
}
public init<S : SequenceType where S.Generator.Element == T>(_ sequence: S) {
set = Set()
for member in sequence {
set.insert(Wrapper(member))
}
}
public init(_ sequence: SetOfProtocol) {set = sequence.set}
@warn_unused_result
public func isSubsetOf(sequence: SetOfProtocol) -> Bool {return set.isSubsetOf(sequence.set)}
@warn_unused_result
public func isSubsetOf<S : SequenceType where S.Generator.Element == T>(sequence: S) -> Bool {return set.isSubsetOf(SetOfProtocol(sequence).set)}
@warn_unused_result
public func isStrictSubsetOf(sequence: SetOfProtocol) -> Bool {return set.isStrictSubsetOf(sequence.set)}
@warn_unused_result
public func isStrictSubsetOf<S : SequenceType where S.Generator.Element == T>(sequence: S) -> Bool {return set.isStrictSubsetOf(SetOfProtocol(sequence).set)}
@warn_unused_result
public func isSupersetOf(sequence: SetOfProtocol) -> Bool {return set.isSupersetOf(sequence.set)}
@warn_unused_result
public func isSupersetOf<S : SequenceType where S.Generator.Element == T>(sequence: S) -> Bool {return set.isSupersetOf(SetOfProtocol(sequence).set)}
@warn_unused_result
public func isStrictSupersetOf(sequence: SetOfProtocol) -> Bool {return set.isStrictSupersetOf(sequence.set)}
@warn_unused_result
public func isStrictSupersetOf<S : SequenceType where S.Generator.Element == T>(sequence: S) -> Bool {return set.isStrictSupersetOf(SetOfProtocol(sequence).set)}
@warn_unused_result
public func isDisjointWith(sequence: SetOfProtocol) -> Bool {return set.isDisjointWith(sequence.set)}
@warn_unused_result
public func isDisjointWith<S : SequenceType where S.Generator.Element == T>(sequence: S) -> Bool {return set.isDisjointWith(SetOfProtocol(sequence).set)}
@warn_unused_result
public func union(sequence: SetOfProtocol) -> SetOfProtocol {
var result = SetOfProtocol()
result.set = set.union(sequence.set)
return result
}
@warn_unused_result
public func union<S : SequenceType where S.Generator.Element == T>(sequence: S) -> SetOfProtocol {return union(SetOfProtocol(sequence))}
public mutating func unionInPlace(sequence: SetOfProtocol) {set.unionInPlace(sequence.set)}
public mutating func unionInPlace<S : SequenceType where S.Generator.Element == T>(sequence: S) {unionInPlace(SetOfProtocol(sequence))}
@warn_unused_result
public func subtract(sequence: SetOfProtocol) -> SetOfProtocol {
var result = SetOfProtocol()
result.set = set.subtract(sequence.set)
return result
}
@warn_unused_result
public func subtract<S : SequenceType where S.Generator.Element == T>(sequence: S) -> SetOfProtocol {return subtract(SetOfProtocol(sequence))}
public mutating func subtractInPlace(sequence: SetOfProtocol) {set.subtractInPlace(sequence.set)}
public mutating func subtractInPlace<S : SequenceType where S.Generator.Element == T>(sequence: S) {subtractInPlace(SetOfProtocol(sequence))}
@warn_unused_result
public func intersect(sequence: SetOfProtocol) -> SetOfProtocol {
var result = SetOfProtocol()
result.set = set.intersect(sequence.set)
return result
}
@warn_unused_result
public func intersect<S : SequenceType where S.Generator.Element == T>(sequence: S) -> SetOfProtocol {return intersect(SetOfProtocol(sequence))}
public mutating func intersectInPlace(sequence: SetOfProtocol) {set.intersectInPlace(sequence.set)}
public mutating func intersectInPlace<S : SequenceType where S.Generator.Element == T>(sequence: S) {intersectInPlace(SetOfProtocol(sequence))}
@warn_unused_result
public func exclusiveOr(sequence: SetOfProtocol) -> SetOfProtocol {
var result = SetOfProtocol()
result.set = set.exclusiveOr(sequence.set)
return result
}
@warn_unused_result
public func exclusiveOr<S : SequenceType where S.Generator.Element == T>(sequence: S) -> SetOfProtocol {return exclusiveOr(SetOfProtocol(sequence))}
public mutating func exclusiveOrInPlace(sequence: SetOfProtocol) {set.exclusiveOrInPlace(sequence.set)}
public mutating func exclusiveOrInPlace<S : SequenceType where S.Generator.Element == T>(sequence: S) {exclusiveOrInPlace(SetOfProtocol(sequence))}
public var hashValue: Int {return set.hashValue}
public var isEmpty: Bool {return set.isEmpty}
public var first: T? {return set.first?.value}
}
extension SetOfProtocol : CustomStringConvertible, CustomDebugStringConvertible {
public var description: String {return set.description}
public var debugDescription: String {return set.debugDescription}
}
extension SetOfProtocol {
public mutating func popFirst() -> T? {
return set.popFirst()?.value
}
}
public func == <T> (left: SetOfProtocol<T>, right: SetOfProtocol<T>) -> Bool {
return left.set == right.set
}