[swift-evolution] [Pitch] making where and , interchangeable in guard conditions.

Erica Sadun erica at ericasadun.com
Tue May 24 13:42:34 CDT 2016


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 <mailto: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 <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <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/b75b04dc/attachment.html>


More information about the swift-evolution mailing list