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

Goffredo Marocchi panajev at gmail.com
Sat May 28 03:14:52 CDT 2016


This I would not cry about. In other languages they are more of a source of pain than anything else.

Sent from my iPhone

> On 28 May 2016, at 09:10, David Hart via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Yet another alternative: would it be possible to disallow commas as variable declaration separators and use them for condition clause separators again:
> 
> let a = 4, b = 8 // becomes illegal and requires to separate them on two lines
> 
> if a > 4, let c = foo(), let d = bar(), c != d { // now comma is not ambiguous anymore
> }
> 
> David.
> 
>>> On 28 May 2016, at 08:25, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> 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.
>> 
>> Yes, which is quite intentional on my part. The `if` statement requires that all of its clauses succeed; if pattern matching and optional testing were boolean expressions, you would use `&&` to link them with each other and with boolean tests. The fact that these are *not* boolean expressions is a mere artifact of Swift's implementation.
>> 
>> I think our best solution is to make Swift act as though these *are* boolean expressions, but ones that can only be used in a limited way: they can only be `&&`ed, because they bind variables that have to be made available in specific blocks. In other words, I think we should paper over the compiler limitations preventing these things from working as expected.
>> 
>> (Actually, it might be interesting to allow `!let` and `!case` statements which are available in the `else` branches of the control structures they're used in, but that's a different story...)
>> 
>> ***
>> 
>> If you'll permit me to go sort of "mad dream" here for a moment, I can actually sort of see a way to do a lot of this in the standard library. Imagine if the `let` and `case` clauses in a conditional produced a type like this:
>> 
>>    enum PatternMatchingResult<BoundValues> {
>>        case failed
>>        case succeeded (BoundValues)
>>    }
>> 
>> `BoundValues` would be the values, if any, extracted through the pattern matching operation. Then you could define operators like these:
>> 
>>    func && <T, U>(lhs: PatternMatchingResult<T>, rhs: @autoclosure () -> PatternMatchingResult<U>) -> PatternMatchingResult<(T, U)> {
>>        guard case .succeeded (let lhsValue) = lhs else {
>>            return .failed
>>        }
>>        guard case .succeeded (let rhsValue) = rhs() else {
>>            return .failed
>>        }
>>        return .succeeded (lhsValue, rhsValue)
>>    }
>> 
>>    func && <T>(lhs: PatternMatchingResult<T>, rhs: @autoclosure () -> Boolean) -> PatternMatchingResult<T> {
>>        guard case .succeeded = lhs else {
>>            return .failed
>>        }
>>        guard rhs() else {
>>            return .failed
>>        }
>>        return lhs
>>    }
>>    
>>    func && <U>(lhs: Boolean, rhs: @autoclosure () -> PatternMatchingResult<U>) -> PatternMatchingResult<U> {
>>        guard lhs else {
>>            return .failed
>>        }
>>        return rhs()
>>    }
>> 
>> And then transform this:
>> 
>>    guard
>>        x == 0 && a == b && c == d &&
>>        let y = optional, w = optional2, v = optional 3 &&
>>        z == 2
>>    else { ... }
>> 
>> Into something like this (where `?` is a sort of "anonymous capture slot"):
>> 
>>    guard case let .success (y, w, v) = (
>>        x == 0 && a == b && c == d &&
>>        Pattern(.some(?), .some(?), .some(?)).result(ofMatchingAgainst: (optional, optional2, optional3)) &&
>>        z == 2
>>    )
>>    else { ... }
>> 
>> Resolving to:
>> 
>>    guard case let PatternMatchingResult.success (y, w, v) = (
>>        (&&)(    // (Boolean, PatternMatchingResult) -> PatternMatchingResult
>>            x == 0,
>>            (&&)(    // (Boolean, PatternMatchingResult) -> PatternMatchingResult
>>                a == b,
>>                (&&)(    // (Boolean, PatternMatchingResult) -> PatternMatchingResult
>>                    c == d,
>>                    (&&)(    // (PatternMatchingResult, Boolean) -> PatternMatchingResult
>>                        Pattern(.some(?), .some(?), .some(?)).result(ofMatchingAgainst: (optional, optional2, optional3)),
>>                        z == 2
>>                    )
>>                )
>>            )
>>        )
>>    )
>>    else { ... }
>> 
>> The `Pattern` type shown here is notional, not an actual thing that would exist as a first-class entity—although that *would* be rather nice to have eventually...
>> 
>> -- 
>> Brent Royal-Gordon
>> Architechies
>> 
>> _______________________________________________
>> 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


More information about the swift-evolution mailing list