10
votes

Note that I have read this post but that post uses a switch statement and it is supposed to do something (return true) when the pattern matches. I, on the other hand, don't want to do anything if the pattern matches and use an if-case statement.

I have this enum:

enum MyEnum {
    case a
    case b(Int)
    case c
    case d
}

Here's an instance of it:

let myEnum: MyEnum = .a

Now I want to do something if myEnum is not .b. Since .b has an associated value, I can't simply use an if statement check:

if myEnum != .b { // compiler error
    // do my thing here
}

So I must use an if-case statement to pattern match it:

if case .b(_) = myEnum {

} else {
    // do my thing here
}

But I really hate the use of the empty if clause. That just looks unswifty to me. I tried to naïvely do this:

if case .b(_) != myEnum { // compiler error!
    // do my thing here
}

Is there a better way to do this other than using an empty if clause?

I still have code that should run regardless of whether the pattern matches, so a guard statement won't work.

5

5 Answers

16
votes

This is purely minimal semantic change of your own code, but note that you can simply "discard" the empty if clause inline with the case pattern matching:

if case .b(_) = myEnum {} else {
    // do your thing here
}

or, leaving out the redundant pattern matching for the associated value of case b:

if case .b = myEnum {} else {
    // do your thing here
}

This looks somewhat like a guard clause, but without exiting the scope.

7
votes

You could use a guard:

guard case .b = myEnum else { 
    // do your stuff here
    return 
}

The downside is that you have to exit the scope...

1
votes

What about:

switch myEnum {
case .b(_):
    break
default:
    // do your thing here
}
1
votes

Create a var on the enum which calculates if your value is not .b(_):

enum MyEnum {

    case a
    case b(Int)
    case c
    case d

    var notB: Bool {
        switch self {
        case .b(_):
            return false
        default:
            return true
        }
    }
}

MyEnum.a.notB // true
MyEnum.b(1).notB  // false
MyEnum.c // true
MyEnum.d // true

Not the greatest answer since there is still a lot of code to do the check, but at least the check is only one line when you actually use it.

1
votes

You can write a computed property and have it return a bool value depending on case

enum MyEnum {
  case a
  case b(Int)
  case c

 var isCaseB: Bool {
     switch self {
       case .b(_):
         return true
       default:
         return false
       }
    }
 }

then in your code cleanly check:

if !enumVal.isCaseB {

}

I checked the answer you mentioned in your question but I wasn't sure if you meant you didn't want to use a switch statement at all or just that you didn't want to mix it in with your other code. I think this is a nice and clean way to check prior to writing whatever implementation you need to do depending on the case.