The goal was to convert items in a generic list into a dictionary for the variable uniqueKeys, but I saw the error:
Cannot subscript a value of incorrect or ambiguous type
I knew something needed to conform to the Hashable protocol and eventually landed on the solution, but I don't completely understand why this solution works.
- I understand why
Tneeds to beHashablesince its' going into a dictionary key, but why alsoCustomSet? - If
CustomSetusesHashablewhy don't I need to write anything in its extension?
initial code
struct CustomSet<T : Comparable > {
private var list: [T]
init(_ list: [T]){
let uniqueKeys = list.reduce(into: [:]){ dict, item in
dict[item, default: 0] += 1
}.keys
self.list = Array(uniqueKeys)
}
}
extension CustomSet : Equatable {
static func == (lhs: CustomSet, rhs: CustomSet) -> Bool {
return lhs.list.count == rhs.list.count && lhs.list.sorted() == rhs.list.sorted()
}
}
I finally resolved it with:
struct CustomSet<T : Comparable > : Hashable where T : Hashable {
private var list: [T]
init(_ list: [T]){
let uniqueKeys = list.reduce(into: [:]){ dict, item in
dict[item, default: 0] += 1
}.keys
self.list = Array(uniqueKeys)
}
}
extension CustomSet : Equatable {
static func == (lhs: CustomSet, rhs: CustomSet) -> Bool {
return lhs.list.count == rhs.list.count && lhs.list.sorted() == rhs.list.sorted()
}
}
I also noticed that factoring into an extension: extension CustomSet: Hashable where T : Hashable doesn't seem to be the same as struct CustomSet<T : Comparable > : Hashable where T : Hashable in terms of adding the Hashable protocol because I still see that error
What I tried
If I add this to the generic type T I still saw the same error.
struct CustomSet<T : Comparable, Hashable >
If I add Hashable to CustomSet I see the error
Cannot convert value of type '[T]' to expected argument type 'UnsafeRawBufferPointer'
and
Inheritance from non-protocol type 'Hashable'
extension CustomSet : Equatable, Hashable {
static func == (lhs: CustomSet, rhs: CustomSet) -> Bool {
return lhs.list.count == rhs.list.count && lhs.list.sorted() == rhs.list.sorted()
}
func hash(into hasher: inout Hasher) {
var hashValue: Int {
var hasher = Hasher()
self.hash(into: &hasher)
return hasher.finalize()
}
}
}
CustomSetdoesn't need to beHashable, your code compiles just fine without theHashableconformance. Btw what's the point of reducing a list into aDictionary, whose keys are the elements of the list if then you're simply assigning the keys of said dictionary tolist? You're not actually unique-ing those keys. - Dávid Pásztorstruct CustomSet<T : Comparable & Hashable >makes your initial code compile. - Martin Rfunc hash(into hasher: inout Hasher)does nothing (apart from declaring an unused computed property). - Martin R