Comparing enum cases while ignoring associated values

Multiple times I have now wanted to compare two values of an enum while ignoring their respective associated values.

enum Foo {
    case string(String)
    case number(Int)
}

let a = Foo.string("str")

a == Foo.string // Binary operator '==' cannot be applied to operands of type 'Foo' and '(String) -> Foo'

I understand why this doesn't work, but... I really want it to! Looking around the web for workarounds has led me to Erica Sadun's article, an interesting gist from the comments of said article, and even a post from Swift 1.2 era asking basically the same question.

All the solutions I've seen so far either require me to manually write type-specific code, or are plain ugly. Even if there are workarounds, though, I'd love for the following to work as well:

foos.contains(.number)

...which could only work if the cases without their associated values were somehow Equatable.

I suppose I'm posting this here out of frustration and hoping that perhaps someone from the Swift team will chime in, because this feels like it should work and just doesn't...

3 Likes

My only use of Sourcery is to auto-generate a subtype on my associated value enums so I can do simple == and != checks for their case names. I would love to see this feature exist in Swift.

It should be easy to do things like the following without resorting to weird quirks or a bunch of extra code

enum State {
  case ready
  case loading(reasons: [String])
}

let stateA = State.ready
let stateB = State.loading(reasons: ["ReasonA", "ReasonB"])

print(stateA.case == stateB.case) //false

if stateA.case != .loading { 
  // do something
}

There are a bunch of hiccups when writing if case let something = .enumCase (including the inability to use != with case let).
I too would love to see it simplified!

Relevant discussion regarding enum ergonomics: Automatically derive properties for enum cases

You can always do

if case .string = a { 
  print("found a string!") 
}
1 Like

I think that, similar to SE-0194, the best way to provide this feature would be to add a CaseDiscriminatable (to be bike-shedded) protocol, for which, like CaseEnumerable a compiler-provided default implementation would be created for same-file extensions.

e.g:

protocol CaseDiscriminatable {
  associatedtype Discriminator: Hashable
  var case: Discriminator
}
4 Likes
Terms of Service

Privacy Policy

Cookie Policy