[swift-evolution] [swift-users] pattern matching in if improvement?

Lukas Stabe ahti333 at gmail.com
Sat Mar 26 22:19:08 CDT 2016


I'd love to see `if value matches pattern`. Every time I use `if case` I have to stop and think to remember the weird syntax. I get where it came from, but I think `matches` better describes what happens here (one is immediately reminded of pattern matching).

I don't know wether this might be unfeasible to do due to compiler performance limitations, but I would support a proposal to replace `if case` with `if value matches pattern`. 

An alternative may be to introduce a custom operator that just calls `~=` with the arguments reversed, but imho this should rather be fixed at the language level.

– Lukas

> On 26 Mar 2016, at 18:13, Erica Sadun via swift-users <swift-users at swift.org> wrote:
> 
>> On Mar 26, 2016, at 3:47 PM, Maury Markowitz via swift-users <swift-users at swift.org> wrote:
>> 
>> Before I stick my head into the other list, consider:
>> 
>>   if statusCode >= 200 && statusCode <= 299
>> 
>> I'm sure examples of something like this occur throughout your code. But the actual semantics of the test is hidden here, you're really testing if statusCode lies within a range. Swift 2.0 has a couple of options for this, but I find them all rather odd. The most recommended is:
>> 
>>   if case 0...100 = someInteger
> 
> While I prefer: 
> 
> if 200...299 ~= statusCode { print("within 200-299") }
> 
> I see that you're asking specifically about case/=. But keep that example in mind because I'm
> going to circle back to it.
> 
>> This syntax has problems. For one thing, it's written backwards compared to most people's code...
>> 
>>   if someinteger == 100
>> 
>> not...
>> 
>>   if 100 == someinteger
>> 
>> so it just *feels* wrong. In addition, the use of "case" seems odd too. And finally, there's the use of the single equals sign in a test, which goes against everything we've learned in C-like languages.
>> 
>> So unless I'm missing something, can anyone offer a reason this wouldn't work?
>> 
>>  if someinteger in 0...100
> 
> This is a built-in problem with "if case/=". Starting with the core statement :
> 
> if case pattern = value {...}
> 
> It's far easier to read and understand the equivalent switch than the one-liner:
> 
> switch (value) {
> case pattern: ...
> default: break
> }
> 
> Once you convert to a switch, the "If this value can be matched to this pattern" 
> becomes a lot less mentally weird but there's also a lot of extra fluff that if case
> attempts to trim away. Here's a concrete example.  "In the case that the pattern 
> Test.A(Int) can be matched to this value then bind x to the associated Int value"
> 
> let value = Test.A(23)
> 
> if case Test.A(let x) = value {
>     print(x) // will print 23
> }
> 
> Again the switch is a lot more intuitive to read, but contains a lot of unneeded
> details that can and should be trimmable:
> 
> switch (value) {
> case Test.A(let x): ...
> default: break
> }
> 
> And here's the oddest example of this Case/= construct I can think of in terms
> of the "read through" not matching the actual programming intent of "In the 
> case that the array indices can be matched to this value" 
> 
> if case array.indices = array.startIndex { print("strange but yup") }
> 
> And its switch equivalent, which is way more obvious in terms of intent:
> 
> switch (array.startIndex) {
> case array.indices: ...
> default: break
> }
> 
> Now back to your original point. Could this be expressed better? For sure. I think these are far more readable:
> 
> if value in range {...} // vs if range ~=
> if value matches pattern {...} // vs if case pattern = value
> 
> And for these specific examples, they'd look like this in an updated Swift that adopted these changes:
> 
> if statusCode in 200...299 { print("within 200-299") }
> if value matches Test.A(let x) { print(x) } // will print 23
> if array.startIndex in array.indices { print("the ~= variation") }
> if array.startIndex matches array.indices { print ("better example Case/=") }
> 
> That said, I've also made my opinion clear over there that the use of "let" and "var"
> in "if let" unnecessarily overloads constant and variable binding (it's testing something 
> that actually acts differently than the standalone let due to unwrapping). This got nowhere
> for a variety of compelling and less compelling reasons. (I'd prefer "if bind" even if it  
> sacrifices a variable variant.)
> 
> I certainly think it's worth doing at least a [Pitch] over in -evolution with the alternate 
> constructs.
> 
> -- E
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160326/ded625e5/attachment.html>


More information about the swift-evolution mailing list