[swift-evolution] [Pitch] making where and , interchangeable in guard conditions.
Jacob Bandes-Storch
jtbandes at gmail.com
Tue May 24 13:47:05 CDT 2016
Could we just require "let" (or var) to introduce every binding, rather
than allowing the combination "if let x = y, z = q, ..."? I always use
"let" anyway; I think it's easier to read.
On Tue, May 24, 2016 at 11:42 AM, Erica Sadun via swift-evolution <
swift-evolution at swift.org> wrote:
> Okay, and here is where the problem is (thanks Chris L)
>
> `z = q` is an expression. It returns Void.
>
> For example:
>
> let q = 5
> var z = 0
> let foo = z = q // foo inferred to have type `()` which may be unexpected
>
> So if you have the following statement:
>
> guard let x = optional, z = q else {...}
>
> where q is non-optional, there's issues in that `q` is not an optional and
> `z = q` is an expression.
>
> -- E
>
>
> On May 24, 2016, at 11:59 AM, Austin Zheng <austinzheng at gmail.com> wrote:
>
> I like the idea in principle.
>
> However, right now you can write something like:
>
> if let a = optionalA, frob = fooBarBaz() { ... }
>
> It's clear that both clauses are optional binding clauses.
>
> With this change, it's not clear anymore whether the second clause is an
> optional binding clause, or a logic test erroneously using '=' instead of
> '=='.
>
> To be fair, though, since assignment in Swift doesn't return the new value
> as it does in C, there is far less room for disastrous bugs caused by this
> sort of mistake.
>
> Austin
>
>
>
> On Fri, May 20, 2016 at 10:07 AM, Erica Sadun via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> *Earlier on Swift Evolution:*
>>
>> Me: "*Is there a technical reason that Swift cannot be expanded to allow
>> arbitrary mixes of conditional binding and boolean assertions within a
>> single compound guard statement?*"
>>
>> Joe Groff: "*No. You already can, we just have the somewhat strange rule
>> that to separate `guard` conditions uses `,` before optional or pattern
>> conditions, but `where` before Boolean conditions. **There's no
>> technical reason we couldn't accept either 'where' or ',' consistently."*
>>
>> guard x == 0,
>> let y = optional where
>> z == 2 {
>> }
>>
>> *Pitch: *
>>
>> I'd like to update Swift's grammar to interchangeably and consistently
>> accept `where` or `,` to separate guard conditions. This would allow a more
>> consistent approach that supports intermingling conditional binding and
>> boolean assertions. Here's a real-world bit of code I was helping someone
>> with a few evenings ago. It's attempting to navigate through some JSON,
>> using optional conditions with where clauses.
>>
>> guard
>> let fileContents = fileContents,
>> let jsonDict = try
>> NSJSONSerialization.JSONObjectWithData(fileContents, options: []) as?
>> NSDictionary,
>> let featuresArray = jsonDict["features"] as? NSArray *where **featuresArray.count
>> > 0,*
>> let featuresDict = featuresArray[0] as? NSDictionary,
>> let coordinatesArray = featuresDict["geometry"] *where **coordinatesArray.count
>> > 0,*
>> let coordinateArray = coordinatesArray[0] as? NSArray *where **coordinateArray.count
>> > 3*
>> else { fatalError("Reason") }
>>
>> Each `where` test is a separate test. While there *are* semantic ties
>> between the conditional binding and the count tests, there *doesn't have
>> to be*. Under Swift's current rules, you must use the `where` keyword
>> to introduce a Boolean test after a binding or pattern, regardless of
>> whether or not there's an underlying semantic link between the two.
>>
>> By removing this requirement and allowing interchangeability between
>> `where` and `,`, you're given the option of tying the boolean to the
>> binding/pattern match or introducing a boolean statement with no connection
>> to previous steps. Here's what this example looks like after excluding
>> `where`:
>>
>> guard
>> let fileContents = fileContents,
>> let jsonDict = try
>> NSJSONSerialization.JSONObjectWithData(fileContents, options: []) as?
>> NSDictionary,
>> let featuresArray = jsonDict["features"] as? NSArray,
>> * featuresArray.count > 0,*
>> let featuresDict = featuresArray.firstObject as? NSDictionary,
>> let coordinatesArray = featuresDict["geometry"],
>> * coordinatesArray.count > 0,*
>> let coordinateArray = coordinatesArray.firstObject as? NSArray,
>> *coordinateArray.count > 3*
>> else { fatalError("Reason") }
>>
>> The motivation for this approach becomes more compelling when the Boolean
>> tests are disjoint from binding or pattern matches.
>>
>> guard
>> minimumShapeCount > 4,
>> let shapes = decompose(map, minimum: minimumShapeCount),
>> availableArea > minimumArea,
>> let map = placeShapes(shapes, availableArea) else {
>> fatalError()
>> }
>>
>> would be allowed compared to current Swift which mandates where between
>> the second and third tests:
>>
>> let shapes = decompose(map, minimum: minimumShapeCount) where availableArea
>> > minimumArea,
>>
>> In my vision, Swift would continue to allow where clauses and expand to
>> allow disjoint Boolean entries.
>>
>> Thoughts?
>>
>> -- E
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160524/9ccf18c4/attachment.html>
More information about the swift-evolution
mailing list