[swift-evolution] [Pitch] making where and , interchangeable in guard conditions.
Erica Sadun
erica at ericasadun.com
Fri May 20 12:07:22 CDT 2016
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160520/f930c697/attachment.html>
More information about the swift-evolution
mailing list