Enum Craziness

Swift 4 enums kinda drove me crazy until I learned to love the bomb. Let’s look at this example enum type:

Swift 4
enum Color {
    case red(Int8)
    case green(Int8)
    case blue(Int8)
}


There’s no way to enumerate all values in the enum. That’s probably because of associated values and the lack of a case attribute. Enums can have associated values, and that turns each case into a static factory function:

Suppose there were a Case type and case attribute. The Case type might be a kind of associated type of the enum (though I dont think that strictly applies here, but go with it a moment). 

Then Color.Cases would be [Color.Case], or perhaps a set of Color.Case if its more sensible for the values to have no order.

More valuable would be a way to ask is this Color value some red? Right now you have to write if case .red = value { … }. Even more valuable is a way to ask Are these two the same Color case? You cannot write an expression for that today.

What about the associated values? Thats complicates the notion of equality to the point Swift cannot make any useful assumptions for you.

What I have done is this, on a type by type basis, as needed. 

Swift 4
extension Color : Equatable {
    /// Operator is true if the two enums are the same vaue, ignoring the associated values.
    /// See .identical(rhs) if you want to compare the associated values as well.
    static func ==(lhs: Color, rhs: Color) -> Bool {
        if case .red = lhs, case .red = rhs { return true }
        if case .green = lhs, case .green = rhs { return true }
        if case .blue = lhs, case .blue = rhs { return true }
        return false
    }
    
    static func ===(lhs: Color, rhs: Color) -> Bool {
        if case .red(let lhsv) = lhs, case .red(let rhsv) = rhs, lhsv == rhsv { return true }
        if case .green(let lhsv) = lhs, case .green(let rhsv) = rhs, lhsv == rhsv { return true }
        if case .blue(let lhsv) = lhs, case .blue(let rhsv) = rhs, lhsv == rhsv { return true }
        return false
    }
}

let c1 = Color.red(64)
let c2 = Color.red(64)
let c3 = Color.red(5)
let d4 = Color.green(64)
c1 == c2    // true
c1 === c2   // true
c1 == c3    // true
c1 === c3   // false
c1 == d4    // false
c1 === d4   // false