# Ability to match a condition to multiple associated values from merged switch cases

**URL:** <https://forums.swift.org/t/ability-to-match-a-condition-to-multiple-associated-values-from-merged-switch-cases/15326>\
**Category:** Pitches\
**Created:** [August 17, 2018, 5:48pm UTC](https://forums.swift.org/t/ability-to-match-a-condition-to-multiple-associated-values-from-merged-switch-cases/15326 "2018-08-17T17:48:43Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [August 17, 2018, 5:48pm UTC](https://forums.swift.org/t/ability-to-match-a-condition-to-multiple-associated-values-from-merged-switch-cases/15326/1 "2018-08-17T17:48:43Z")

</div>

I just had a small issue with a switch statement where I for some reason assumed that the `where` clause was already applied to every associated value of a merged switch case.

```swift
enum Permission {
  case notSupported(UInt8)
  case readOnly(UInt8)
  case readWrite
}

let permission = Permission.notSupported(0)

switch permission {
case .notSupported(let code),
     .readOnly(let code) where code > 0:
  /* create the right error value */
default:
  /* create the default error value */
}

```

The above example actually will succeed with in the first case instead of landing in the `default` branch, because the `where` clause is only applied to the second `readOnly` case.

There is also a diagnostics bug ([SR-8567](https://bugs.swift.org/browse/SR-8567)) in the above switch which prevents from triggering an expected warning that might have helped me finding the issue in that pattern. If we restructure the switch statement then the right diagnostics is triggered and the compiler emits a warning:

```swift
case .notSupported(let code), .readOnly(let code) where code > 0: // 'where' only applies to the second pattern match in this case

```

In my use case the solution was to remove the `where` clause entirely and add a `guard code > 0 else { break }` below the case since `default` case was also breaking out the current control flow.

The issue I'm trying to describe next is trying to avoid the same situation and reduce some of the boilerplate code wile providing a more flexible way of expressing a global condition.  
In general you may want to merge multiple cases in a switch statement and match them from left to right, top to bottom. You may also wish to extract an associated value from any merged case. The only constraint that is required from the developer to be applied, is that the associated value has to have the same instance name and be of the same type. If you also need to apply a `where` clause to the extracted value in order to return the control flow to the switch so it matches the next case you have to replicate the same `where` clause over and over again:

```swift
switch something {
case .a(let value) where checkCondition(of: value),
     .b(let value) where checkCondition(of: value),
     .c(let value) where checkCondition(of: value): 
   ...
case .otherCase:
   ...
default:
   ....
}

```

To reduce the repetition of the `where` clause and allow to return the control flow to the switch statement so it can match next case, I propose a new way we can express the `where` clause in switch statements that is automatically applied to every associated value in the current branch.

```swift
switch something {
case where checkCondition(of: value) in .a(let value), .b(let value), .c(let value): 
   ...
case .otherCase:
   ...
default:
   ...
}

```

If this idea reaches some traction and positive feedback, I'd happily write a draft proposal and see if I can find someone willing to implement that feature.

Thoughts?

* * *

Edit: The above solution introduces a syntax by reusing the `where` clause in an unambiguous way which leads us to the

```swift
case where condition in cases

```

syntax. However I think we can also go a step further and eliminate the `where` clause entirely. Then we'd get

```swift
case condition in cases

```

which is quite similar to

```swift
for value in sequence /* where condition */

```

---

<div class="post-metadata">

**Author:** ![gabriel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gabriel/32/4450_2.png) [@gabriel](https://forums.swift.org/u/gabriel)\
**Post date:** [August 18, 2018, 11:11am UTC](https://forums.swift.org/t/ability-to-match-a-condition-to-multiple-associated-values-from-merged-switch-cases/15326/2 "2018-08-18T11:11:12Z")

</div>

> we can also go a step further and eliminate the `where` clause entirely, `case condition in cases`

I would vote to leave the `where` keyword in there. Yes, `case condition in cases` is attractively similar to `for value in sequence`, but perhaps... it shouldn't be?

Considering: `for value in sequence` and `case eval(of: condition) in .a(let value), .b(let value)`, it is true that both `in sequence` and `in .a(let value), .b(let value)` are sequences of values, but `for value` is concerned with value assignment and `case eval(of: condition)` is concerned with condition evaluation. How to clearly set them apart? It is the `where` keyword that usually "extends" a statement with condition evaluation, as in `for value in sequence where eval(of: condition)`. An analogous situation happens with `.first(where: { eval(of: condition) })` or even `extension LHSType where Self: RHSType` - seeing the `where` keyword immediately implies that a condition follows.

All programmers used to `case .a(let value) where eval(of: condition)` will likely immediately understand `case where eval(of: condition) in .a(let value), .b(let value)`, without Reading The Fine Manual.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [August 18, 2018, 11:18am UTC](https://forums.swift.org/t/ability-to-match-a-condition-to-multiple-associated-values-from-merged-switch-cases/15326/3 "2018-08-18T11:18:25Z")

</div>

Well I personally like either way because both reads well, but those are good points to be aware of. Thank you for sharing your opinion.
