[swift-evolution] [swift-evolution-announce] [Review] SE-0099: Restructuring Condition Clauses

Russ Bishop xenadu at gmail.com
Tue May 31 17:57:09 CDT 2016


>> On May 27, 2016, at 5:30 PM, Erica Sadun via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> 
>>> On May 27, 2016, at 6:26 PM, Brent Royal-Gordon <brent at architechies.com> wrote:
>>> 
>>>> guard
>>>> x == 0 && a == b && c == d &&
>>>> let y = optional, w = optional2, v = optional 3 &&
>>>> z == 2
>>>> else { ... }
>>>> 
>>>> Figuring out where to break the first line into expression and into condition (after the `d`) could be very challenging to the compiler.
>>> 
>>> I'm not sure it is. `let` and `case` are not valid in an expression, so an `&&` followed by `let` or `case` must be joining clauses. On the other side of things, Swift's `&&` doesn't ever produce an optional, so if we're parsing an expression at the top level of an if-let, an `&&` must indicate the end of the clause. An if-case *could* theoretically include an `&&`, but pattern matching against a boolean value seems like a fairly useless thing to do in a context that's specifically intended to test booleans.
>> 
>> Let me answer in another way that speaks to my background which isn't in compiler theory: The use of && may produce cognitive overload between the use in Boolean assertions and the use in separating condition clauses.
>> 
>> -- E

In reality I often write if/guard statements using && exactly the way Brent proposes, only to go back and rework it for syntax correctness. I started this message intending to argue for Brent’s proposal but I think I’ve talked myself out of it :)


> On May 28, 2016, at 10:26 AM, Chris Lattner via swift-evolution <swift-evolution at swift.org> wrote:
> 
>> 
>> My suggestion would be to reuse our normal && operator:
>> 
>> 	guard
>> 		x == 0 &&
>> 		let y = optional &&
>> 		z == 2
>> 		else { ... }
>> 
>> This would obviously be a built-in `&&` separate from our existing, infix operator `&&`. 
> 
> Yes, this is technically feasible, but it has the opposite problem from the above: && is very closely associated (in terms of programmer mindspace) with boolean conditionals, and the let/case clauses are *not* boolean conditions.


I initially didn't think && represents a problem, but I realized as I was working on this message there definitely is a serious issue: ||. I don’t see how you can work around it either and that seems to kill the idea of using && no matter how you slice it.

	guard
		x == 0 &&
		let y = optional ||
		z == 2 && y == 5 //is y optional or not?!?
		else { … }

You can’t have the optional let binding shortcut and use boolean values this way. You’d have to figure out if the expression always requires “y = optional” to succeed, then y’s type would be non-optional, otherwise y would be optional. That seems surprising and confusing.



What I really want is commas to separate different kinds of clauses because many cases read cleaner as a single line and C ruined semicolons for me, especially their use in for statements.


> 
> The ambiguity is between “case” and “let” conditions, specifically because “case” takes a pattern, and “let” is a valid pattern:
> 
> guard (pattern1) = expr1, let x = expr2 else
> 
> can be:
> 
> guard (pattern1) = expr1, let (x) = expr2 else
> 
> or:
> 
> guard (pattern1) = expr1, (let x) = expr2 else


I am probably missing something but why is this the case? In all of these forms the let is unambiguous; it either precedes the enum case or pattern (itself enclosed in parens), or the let is contained in the parens.

    if case let .Point(x, y) = value, let z = optional { }
    if case let (x, y) = value, let z = optional { }
    if case .Point(let x, _) = value, let z = optional { }
    if case (let x, 1.0) = value where x != 0.0, let z = optional { }



Russ


More information about the swift-evolution mailing list