egnha
egnha

Reputation: 1197

Sets of a given size as a Swift type

In Swift, is there a way to construct a type of “sets of a given size?”(Despite the absence of dependent types in Swift, is such a construction nonetheless possible without excessive “contortions?”)

As an example, I would like to be able to define a parameterized type SetOfSizeTwo<T> whose instances are sets comprising of exactly two objects of (Hashable) type T.

Currently, I am using a poor man’s proxy:

struct SetOfSizeTwo<T> where T: Hashable {
    var set = Set<T>(minimumCapacity: 2)
}

However, this type does not force the property set to be of size of 2.

Update

The blog article A hack for fixed-size arrays in Swift, by Ole Begemann, leads me to believe that a robust construction of a fixed-sized-set type in Swift 4 is non-trivial, if at all possible.

Upvotes: 0

Views: 71

Answers (1)

Michal
Michal

Reputation: 15669

Here is one approach, as closest as I could get, to suit your needs. It is a bit rough around the edges and needs some polishing, but I think you'll get the idea:

class Size {
    let size: Int

    init(size: Int) {
        self.size = size
    }

    required init() {
        self.size = 0
    }
}

class SizeOne: Size {
    private override init(size: Int) {
        super.init(size: size)
    }

    required init() {
        super.init(size: 1)
    }
}

class SizedSet<S, T> where S: Size, T: Hashable {
    private var set: Set<T>
    private let maximumSize: S

    init() {
        set = Set<T>()
        maximumSize = S()
    }

    func insert(item: T) {
        if !set.contains(item) && set.count + 1 <= maximumSize.size {
            set.insert(item)
        }
    }

    func remove(item: T) {
        set.remove(item)
    }

    func contents() -> Set<T> {
        return set
    }
}

Usage:

let set: SizedSet<SizeOne, Int> = SizedSet()
print(set.contents())
// []

set.insert(item: 1)
print(set.contents())
// [1]

set.insert(item: 2)
print(set.contents())
// [1]

Upvotes: 1

Related Questions