# \[Pitch\] Proposal for Enhanced Enum Pattern Matching Syntax in Swift

**URL:** <https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007>\
**Category:** Pitches\
**Created:** [September 28, 2024, 8:07pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007 "2024-09-28T20:07:43Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![tiagocanto01](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tiagocanto01/32/28562_2.png) [@tiagocanto01](https://forums.swift.org/u/tiagocanto01)\
**Post date:** [September 28, 2024, 8:07pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/1 "2024-09-28T20:07:43Z")

</div>

**Introduction**

Swift's powerful enum feature, especially with associated values, is a cornerstone of the language's type safety and expressiveness. However, the current pattern matching syntax can be cumbersome when using the `if case` construct, particularly in scenarios where the enum type must be inferred. This proposal suggests a new syntax, `if <var> case`, to simplify and enhance the pattern matching experience.

**The Problem**

When using the `if case` construct, we often face issues with autocompletion and clarity. For example:

```swift
if case .qrcode(let value) = code {
    // Process value
}

```

In this structure, when typing `.`, Xcode cannot infer the enum type associated with `code`, leading to a poor autocompletion experience. As a result, we must either explicitly declare the type before the case or rely on trial and error.

**Proposed Solution**

To address these issues, I propose a new syntax that allows developers to directly reference the variable before the case statement:

```swift
if code case .qrcode(let value) {
    // Here, 'value' is available if 'code' is of type .qrcode
}

```

### Advantages of the Proposed Syntax

1. **Improved Clarity** : This syntax maintains the logical flow of condition checking while making it clear which variable is being checked against the enum case.

2. **Enhanced Autocompletion** : Since `code` is defined before `case`, the compiler can infer the type of `code`, allowing for better autocompletion for associated values.

3. **Reduced Verbosity** : This approach eliminates the need for redundant type declarations, resulting in cleaner and more concise code.

4. **Consistency with Language Principles** : The proposed syntax aligns with Swift's goals of safety, clarity, and expressiveness, providing a more natural way to perform pattern matching.

### Example with `guard`

The proposed syntax could also be effectively used with `guard`, allowing for early exits when dealing with enums:

```swift
guard code case .qrcode(let value) else {
    // Handle the case where 'code' is not a .qrcode
    return
}
// Proceed with 'value' if 'code' is of type .qrcode

```

This allows developers to ensure that they only proceed with valid values, maintaining clean and readable code.

### Conclusion

The `if <var> case` syntax presents an opportunity to streamline pattern matching in Swift, enhancing both developer experience and code readability.

---

<div class="post-metadata">

**Author:** ![YOCKOW](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/yockow/32/20636_2.png) [@YOCKOW](https://forums.swift.org/u/YOCKOW)\
**Post date:** [September 28, 2024, 11:58pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/2 "2024-09-28T23:58:59Z")

</div>

I'd like your idea, but I personally prefer `is` keyword requirement for intuition.  
It'd be somthing like:

> [@Proposal draft for \`is case\` (pattern-match boolean expressions)](https://forums.swift.org/t/proposal-draft-for-is-case-pattern-match-boolean-expressions/58260):
>
> Hi, all. I recently ran into a situation where is case would have been really helpful, and that prompted me to take a look at the history of this moderate proposal. It turns out it's been discussed [[every](https://forums.swift.org/t/allowing-non-binding-pattern-matching-as-a-bool-expression/294/2)] [[year](https://forums.swift.org/t/proposal-treat-case-foo-bar-as-a-boolean-expression/2546)] [[since](https://forums.swift.org/t/testing-enum-cases-with-associated-values/7091)] [[Swift](https://forums.swift.org/t/comparing-enums-without-their-associated-values/18944)] [[went](https://forums.swift.org/t/pitch-case-expressions-for-pattern-matching/20348)] [[open](https://forums.swift.org/t/proposal-sanity-check-assigning-a-case-statement-to-a-boolean/40584)] [[source](https://forums.swift.org/t/enumeration-case-evaluates-as-boolean/54266)], and that's just in the Evolution section. Due to my RSI I can't actually be the one to implement it, but one thing I can contribute is a written-up proposal draft. Thoughts? Implementation volunteers? (And no, assume it's too late for this to mak…

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [September 29, 2024, 3:07am UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/3 "2024-09-29T03:07:27Z")

</div>

I think they're complementary, `is case` would be a boolean expression, but this supports full matching with bindings.

Precise spelling aside, the one drawback I see is that today all the patterns that introduce bindings—other than parameters—are on the left side of a statement, beginning just after an introducer (`let`, `var`, `case`, or `for`, sometimes combined with `if`, `guard`, or `while`). This would break that rule. But it's probably worth it for the code-completion benefits, and it's not actually hard to understand.

---

<div class="post-metadata">

**Author:** ![tiagocanto01](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tiagocanto01/32/28562_2.png) [@tiagocanto01](https://forums.swift.org/u/tiagocanto01)\
**Post date:** [September 29, 2024, 12:09pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/5 "2024-09-29T12:09:25Z")

</div>

I get your point about bindings typically being on the left side, but I think there's a good parallel with how it's already done in `switch` statements.

For example, in a `switch`:

```swift
switch code {
case .qrcode(let value):
    // Handle value
default:
    break
}

```

The binding happens with the case itself, similar to what I'm proposing. The idea with `if code case .qrcode(let value)` is to create something like a one-clause `switch` but more streamlined for cases where you're only checking one condition.

This keeps the pattern familiar and makes code completion better, without adding much complexity.

---

<div class="post-metadata">

**Author:** ![Jnosh](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jnosh/32/37375_2.png) [@Jnosh](https://forums.swift.org/u/Jnosh)\
**Post date:** [September 29, 2024, 2:18pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/6 "2024-09-29T14:18:00Z")

</div>

I am strongly in favor of an enhancement in this area. I have often been frustrated at the lack of code completion with the current `if case` syntax. It's not a major issue but it is a very noticeable problem that I would like to see fixed.

I don't have strong feelings on the proposed syntax. It looks fine at a first glance but I would await the to be expected bike shedding before giving a firm opinion.

I would expect this syntax to allow matching just the case `if myEnum case .qrcode {}` or matching including bindings `if myEnum case .qrcode(let value) {}` and having a single new addition cover both the `is case` use case and improving autocompletion would be nice.

---

<div class="post-metadata">

**Author:** ![Lancelotbronner](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lancelotbronner/32/22071_2.png) [@Lancelotbronner](https://forums.swift.org/u/Lancelotbronner)\
**Post date:** [September 29, 2024, 2:23pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/7 "2024-09-29T14:23:56Z")

</div>

I’m generally a fan of the C# pattern-matching, mostly because it reads naturally from left to right the way I would say it.

I think this is definitely a step in the right direction, both for completion and being easier to remember!

It could then naturally ease into “is case” which I would love to have which could naturally ease into other “is” patterns.

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [September 29, 2024, 2:26pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/8 "2024-09-29T14:26:20Z")

</div>

`is case` would be ideal to use with Swift Testing:

```swift
#expect(x is case .y)

```

Versus what you need to do today:

```swift
if case .y = x {} else {
  Issue.record("x wasn't .y")
}

```

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [September 29, 2024, 2:51pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/9 "2024-09-29T14:51:31Z")

</div>

Having `is case` usable as both a Boolean expression and as a way to bind patterns in a condition list seems ideal to me. I think we could make this work:

```swift
enum E { case a(Int) }
let e = E.a(10)

_ = e is case .a // true
_ = e is case .a(10) // true
_ = e is case .a(11) // false
_ = e is case .a(let x) // error: cannot bind variables in 'is case'
                         // outside of a control flow statement condition
if e is case .a(let x) {
  print(x) // "10"
}
// guard, while, etc. are similar

```

> [@grynspan](#):
>
> `is case` would be ideal to use with Swift Testing:
> 
> ```swift
> #expect(x is case .y)
> 
> ```

In my experience, when I want to match an enum in a test, I usually want to also bind a payload and write an expectation about that as well. If I have an enum where all I care about is the case discriminator, chances are that's a payload-free enum where I could just make it `Equatable` and write `#expect(x == .y)` instead.

I don't know how we would combine `#expect` with bindings though. If we extended `if/switch` expressions to be allowed as function arguments, we could at least write this, without any other changes:

```swift
#expect(if case .a(let x) = e { x == 10 } else { false })

```

Then, if `is case` was added:

```swift
#expect(if e is case .a(let x) { x == 10 } else { false })

```

Still not as concise as I'd like, but an improvement on what we have today.

---

<div class="post-metadata">

**Author:** ![mbrandonw](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mbrandonw/32/349_2.png) [@mbrandonw](https://forums.swift.org/u/mbrandonw)\
**Post date:** [September 29, 2024, 3:37pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/10 "2024-09-29T15:37:57Z")

</div>

It would be nice to have a better syntax (as well as key paths for enum cases that @stephencelis and I have pitched a few times), but it is possible to accomplish a lot of this in Swift today. You just need to use macros, which means there are a lot of downsides that come with it (like slow compile times).

But, if you are willing to incur those costs, then we have a library called [Case Paths](https://github.com/pointfreeco/swift-case-paths/) that allows you to write an enum like this:

```swift
import CasePaths

@CasePathable
enum Loadable<Value> {
  case loading
  case loaded(Value)
}

```

…and then you can check the case of an enum with the `is` method:

```swift
let value = Loadable.loaded(42)
#expect(value.is(\.loaded))

```

Note that we are using a key path `\.loaded` to abstractly reference the case of an enum.

And you can extract a value for a case using a `[case:]` subscript:

```swift
#expect(value[case: \.loaded] == 42)

```

It gives you a very familiar key path syntax, but for the cases of an enum. And it also works for nested enums automatically:

```swift
@CasePathable
enum Status { case on, off }

let status = Loadable.loaded(Status.on)
#expect(statue.is(\.loaded.on))

```

Further, if want computed properties to be automatically added to your enum for each case, then you just have to add `@dynamicMemberLookup`:

```swift
@CasePathable
@dynamicMemberLookup
enum Loadable<Value> {
  case loading
  case loaded(Value)
}

let value = Loadable.loaded(42)
#expect(value.loaded == 42)

```

It would of course be far better if these features were built into the language, and we would love if Swift sherlocked any of this. But, in the meantime, it is possible to make working with enums and cases more expressive.

---

<div class="post-metadata">

**Author:** ![tera](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tera/32/38201_2.png) [@tera](https://forums.swift.org/u/tera)\
**Post date:** [September 29, 2024, 4:10pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/11 "2024-09-29T16:10:21Z")

</div>

> [@](#):
>
> ```swift
> if code case .qrcode(let value) {
> 
> ```

(either with or without `is` between `code` and `case`) is better then what we have today. Not only in the autocompletion support, I often find myself searching for "how to do swift if case" no matter how many times I used it already. That the enum variable is at the end in the current syntax (contrary to switch) makes it so weird.

---

<div class="post-metadata">

**Author:** ![vns](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/vns/32/37396_2.png) [@vns](https://forums.swift.org/u/vns)\
**Post date:** [September 29, 2024, 5:09pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/12 "2024-09-29T17:09:19Z")

</div>

As I was skeptical at the first sight, the need to remember how the case is named (if there is something to remember in the first place) when writing if statement, and autocomplete is basically useless here because variable goes after, the change makes a lot of sense!

---

<div class="post-metadata">

**Author:** ![FlorianPircher](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/florianpircher/32/39919_2.png) [@FlorianPircher](https://forums.swift.org/u/FlorianPircher)\
**Post date:** [September 29, 2024, 5:55pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/13 "2024-09-29T17:55:17Z")

</div>

> [@allevato](#):
>
> Then, if `is case` was added:
> 
> ```swift
> #expect(if e is case .a(let x) { x == 10 } else { false })
> 
> ```
> 
> Still not as concise as I'd like, but an improvement on what we have today.

Would

```swift
#expect(e is case .a(10))

```

not be possible?

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [September 29, 2024, 6:21pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/14 "2024-09-29T18:21:12Z")

</div>

> [@FlorianPircher](#):
>
> Would
> 
> ```swift
> #expect(e is case .a(10))
> 
> ```
> 
> not be possible?

For that particular case, sure—perhaps I oversimplified it. Consider something that isn't strict equality of the bound value `x` so that it can't be written simply as an expression pattern:

```swift
guard case let .a(let x) = e else {
  Issue.record("e wasn't .a")
  return
}
#expect(x.someMember == somethingElse)

```

or even

```swift
guard case let .a(let x) = e else {
  Issue.record("e wasn't .a")
  return
}
#expect(x > 10)

```

* * *

Not sure if this would overly complicate things, but what if an `is case` expression outside of a control flow statement could have bindings but the bindings would only be visible within a trailing `where` clause:

```swift
#expect(e is case .a(let x) where x.someMember == somethingElse)

```

I don't know how I feel about that, though. The expression grammar is complicated enough as it is...

---

<div class="post-metadata">

**Author:** ![grynspan](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/grynspan/32/15315_2.png) [@grynspan](https://forums.swift.org/u/grynspan)\
**Post date:** [September 29, 2024, 8:39pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/15 "2024-09-29T20:39:25Z")

</div>

> [@allevato](#):
>
> In my experience, when I want to match an enum in a test, I usually want to also bind a payload and write an expectation about that as well.

We've had enough requests for just case-level pattern matching that we'd probably want to support `is case` if it came to be. But yes, a simple `x == .y(z)` works today as expected when the type is `Equatable`.

> [@allevato](#):
>
> Still not as concise as I'd like, but an improvement on what we have today.

I think we'd be happy to work with whatever new syntax might be added.

---

<div class="post-metadata">

**Author:** ![AlexisQapa](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexisqapa/32/7159_2.png) [@AlexisQapa](https://forums.swift.org/u/AlexisQapa)\
**Post date:** [September 29, 2024, 10:45pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/16 "2024-09-29T22:45:41Z")

</div>

For those who need auto completion, you can always start by writing first the `= x` part then you have auto completion for dot notation.

If something is to be changed in this area, I’m more inclined to something more general like the direction taken by CasePaths.

---

<div class="post-metadata">

**Author:** ![nonameplum](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nonameplum/32/6450_2.png) [@nonameplum](https://forums.swift.org/u/nonameplum)\
**Post date:** [September 30, 2024, 9:39am UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/17 "2024-09-30T09:39:49Z")

</div>

I would lean towards more general improvements like `@CasePathable` is doing.

I'm not using it only because of the Swift Macro's current usage downside.

I'm observing and wishing that at some point `CasePathable` abilities would finally land directly into the language. It solves a great amount of `enum` conveniences. Not only `is` to test `case` but also, query variables without boilerplate, `CasePath` and its composability.

---

<div class="post-metadata">

**Author:** ![kebo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/kebo/32/6918_2.png) [@kebo](https://forums.swift.org/u/kebo)\
**Post date:** [September 30, 2024, 4:13pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/18 "2024-09-30T16:13:21Z")

</div>

I agree that the current syntax has an autocompletion problem.

However, the proposed solution can't solve the same problem in `for case`.

```swift
for case .foo(let value) in array {
    // ...
}

```

---

<div class="post-metadata">

**Author:** ![Gabardone](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gabardone/32/3312_2.png) [@Gabardone](https://forums.swift.org/u/Gabardone)\
**Post date:** [October 2, 2024, 4:24pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/19 "2024-10-02T16:24:01Z")

</div>

Bear with me, I'm just thinking out loud, but I've used the existing syntax and the pointfree macros and thinking at what I'd want from all of this I ended up with something like this:

```swift
enum Transportation {
    case bus(passengers: Int)
    case truck(load: Double, towing: Double)
    case train(length: Double)

    // All of the following gets magically generated by the compiler:

    var bus: Int?
    var truck: (Double, Double)?
    var train: Double?

    enum Case: Equatable {
        case bus
        case truck
        case train
    }

    var case: Case // Dunno if this will work that great with `case` being a keyword.
}

```

This would also allow keypath use and make all of the use cases we're discussing here into common Swift idioms.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [October 2, 2024, 4:37pm UTC](https://forums.swift.org/t/pitch-proposal-for-enhanced-enum-pattern-matching-syntax-in-swift/75007/20 "2024-10-02T16:37:58Z")

</div>

The language steering group has provided the following feedback to proposed solutions in this space in the past:

> [@\[Pitch\] is case expressions](https://forums.swift.org/t/pitch-is-case-expressions/64185/69):
>
> I'm sorry for leaving you hanging for so long. The Language Steering Group talked about this proposal. We agree that there's a lot of room for improvement in this part of the language, and this specific proposal seems to be high-quality: it is thorough and well thought out. Nevertheless, we don't feel comfortable running proposals in the general space of pattern matching at the moment, because we don't feel like we have a good understanding of where the language ought to be going. We therefo…
