[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