Is there a way to check if an enum is a specific case without switching on it?

I've seen this syntax:

enum E {
    case foo, bar
}

let f: E = .bar

if case .foo = f {
    ...
}

But this doesn't work:

XCTAssert(case .foo = f)

I'm guessing that syntax is magic and only works in an if statement. Which seems silly to me. Is there no other way to do the same check, but capture it as a Bool expression?

enum Foo: Equatable {
  case zero
  case one(Int)
}

let a: Foo = .zero
let b: Foo = .one(0)

XCTAssertEqual(a, .zero) // ok
XCTAssertEqual(b, .one(0)) // ok

That works if I own the enum, but I don't own Result for example, which doesn't conform to Equatable, and you're not supposed to add conformances to types you don't own.

Also, I'm not asking to check for absolute equality (payloads and all), I just want case equality in this instance. :/

You can assert the Result's value.

let some: Result<Int, Error> = .success(0)
XCTAssertEqual(some.value, 0)

I'm not trying to compare payloads, I just want to check if the enum is a specific case.

I want to be able to do this:

let f: E = .foo
// whether f is .bar, regardless of whether .foo or .bar have payloads
let booleanExpression = case .bar = f

If this functionality doesn't exist, it seems like a hole in the language to me.

If you want to check for a case, that's not gonna work

let some: Swift.Result<Int, Error> = .success(0)
XCTAssertEqual(some, .success(_)) // error
XCTAssertEqual(some, Swift.Result<Int, Error>.success(_)) // error

I wrote a pitch on it a while ago: Comparing enums without their associated values

I just need to find some time to figure out the best way to do it.

Anyhow, in Result case, you can just check for value or error, which is the same as checking for success or failure cases.

Result conforms to Equatable and Hashable, when its contained Success and Failure types do. Making it more generally Equatable would not do what you want, unless you violated the requirements of Equatable and made .success(1) == .success(2). I believe there have been discussions of case equality before but they haven't gone anywhere specific. You can find other threads around enum ergonomics (I think that's what they were called).

Swift's Result type has no properties, so that isn't possible.

1 Like

That thread seems to be aimed at the problem I'm trying to solve. I want a solution that works for any enum, regardless whether it has a payload or not. Some expression that evaluates to a Bool, like f is .foo or case .foo = f without the if.

Swift already has this functionality built in: it's the logic behind a switch statement. It just doesn't expose it anywhere but if case ...

Ah, I forgot. I have an extension on it that adds these convenience properties.

I may just write a more formal pitch in hopes someone can implement it then. Thanks!

2 Likes
Terms of Service

Privacy Policy

Cookie Policy