Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hashable enum in Swift

Tags:

enums

swift

hash

I'd like to have an enum with two cases with a Hashable associated type each conform to Hashable, like so:

enum WordOrNumber {
    case Word(String)
    case Number(Int)
}

The first idea I had for hashing was the following:

extension WordOrNumber: Hashable {
    var hashValue: Int {
        switch self {
            case let .Word(word): 
                return word.hashValue & ~1 // ends in 0
            case let .Number(number):
                return number.hashValue | 1 // ends in 1
        }
    }
}

What I'm not sure about, is how this will interact with buckets in Swift's Dictionary and Set implementations.

Is it be better to differentiate the two cases by the LSB or MSB, or by a bit somewhere in the middle?

I assume it doesn't make any difference to shift the hashValues left by one and then adding 1, or not, but I would be interested to know if this isn't the case.

EDIT: I just tested this, and it looks like the hashValue of an Int is the value itself. This is obviously a problem, since you often get ints in succession, like in an enum Bla: Int {}. So my new and improved(?) hashValue is:

extension WordOrNumber: Hashable {
    var hashValue: Int {
        switch self {
            case let .Word(word): // ends in 0
                return word.hashValue << 1
            case let .Number(number): // ends in 1
                return number.hashValue << 1 &+ 1
        }
    }
}

The above question about LSB and MSB still stands.

like image 996
Sasha Lopoukhine Avatar asked May 16 '16 13:05

Sasha Lopoukhine


People also ask

Is enum hashable?

Enum is Hashable and CustomStringConvertible, but uses description as key rather than hashValue. My enumerated type conforms to both Hashable and CustomStringConveritble, so it implements hashValue -> Int and description -> String.

What does hashable mean in Swift?

In Swift, a Hashable is a protocol that provides a hashValue to our object. The hashValue is used to compare two instances. To use the hashValue , we first have to conform (associate) the type (struct, class, etc) to Hashable property. For example, struct Employee: Hashable { ... }

Is string hashable in Swift?

Many types in the standard library conform to Hashable : Strings, integers, floating-point and Boolean values, and even sets are hashable by default.

What is hash value in enum Swift?

//enum hash value is the logic index. //enum raw value is defined by the raw type. //enum no specified raw value follows the hash value. //enum hash value is int.


1 Answers

Having something like:

extension WordOrNumber: Hashable {
    var hashValue: Int {
        switch self {
        case .Word(let value):
            return value.hashValue
        case .Number(let value):
            return value.hashValue
        }
    }

    static func ==(lhs: WordOrNumber, rhs: WordOrNumber) -> Bool {
        switch (lhs, rhs) {
        case (.Word(let lhsValue), .Word(let rhsValue)):
            return lhsValue == rhsValue
        case (.Number(let lhsValue), .Number(let rhsValue)):
            return lhsValue == rhsValue
        default:
            return false
        }
    }
}

... should be enough.

like image 89
eMdOS Avatar answered Nov 12 '22 19:11

eMdOS