> On Jun 12, 2016, at 4:46 AM, Brent Royal-Gordon <br...@architechies.com> > wrote: > > When I suggested this syntax in the acceptance thread for SE-0099, Chris said > it should be written up as a proposal. I'm sure this will get lost in the > WWDC shuffle, but here goes.
Hi Brent, I’m sorry that I haven’t had time yet to read the down thread responses, but I don’t see how this can work: “if let pattern = expr” is sugar for “if case let pattern? = expr”, so this would either: a) only apply to tuple literals on the right side or b) not work, since this syntax above already means “if case let (a,b,c)? = expr”. If you pick a, then it is makes tuple literals inconsistent with other expressions, which seems to make the language more confusing and less orthogonal. -Chris > Tuple-Based Compound Optional Binding > Proposal: TBD > Author: Brent Royal-Gordon <https://github.com/brentdax> > Status: TBD > Review manager: TBD > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#introduction>Introduction > > This proposal enhances optional binding with a new, tuple-based syntax for > binding multiple values. It replaces functionality lost in SE-0099 with a > syntax compatible with the new design. > > Swift Evolution Discussion: [Accepted with Revision] SE-0099 Restructuring > Condition Clauses > <http://thread.gmane.org/gmane.comp.lang.swift.evolution/19452/focus=20139> > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#motivation>Motivation > > In Swift 2, it was possible to bind multiple optional values in a single if > let, guard let, or while let clause: > > guard let a = opt1, b = opt2, c = opt3 else { ... } > SE-0099 > <https://github.com/apple/swift-evolution/blob/master/proposals/0099-conditionclauses.md> > simplified the syntax of conditional statements, but removed this feature so > that , could instead separate different conditional clauses. Code like this > must now use three separate optional binding clauses: > > guard let a = opt1, let b = opt2, let c = opt3 else { ... } > The similar case clause sidesteps this problem because it can pattern-match > tuples. Hence, you can put several patterns in a tuple on the left side of > the =, and a matching number of values in a tuple on the right side, and > match them all with one case clause: > > guard case (.none, .none, .none) = (opt1, opt2, opt3) else { ... } > This doesn't conflict with the clause separation syntax because the commas > are within parentheses. However, the analogous syntax for optional bindings > is not permitted: > > guard let (a, b, c) = (opt1, opt2, opt3) else { ... } > // error: initializer for conditional binding must have > // Optional type, not '(Int?, Int?, Int?)' (aka > // '(Optional<Int>, Optional<Int>, Optional<Int>)') > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#proposed-solution>Proposed > Solution > > We should extend optional binding clauses to permit a tuple of optional > values on the right of the = and a tuple of constants with identical arity on > the left. Swift should test each element of the tuple on the right, and if > none of them are nil, bind them to the constants on the left. > > Nothing in this proposal should change the way optional binding handles an > optional tuple (T, U)?, as opposed to a tuple of optionals (T?, U?). Even an > optional tuple of optionals (T?, U?)? should continue to be handled as before. > > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#detailed-design>Detailed > Design > > No change to the formal grammar is necessary, as the pattern and initializer > productions in the optional-binding-head rule can already match tuples: > > optional-binding-head : 'let' pattern initializer > Rather, Sema should be modified to detect this situation and generate > appropriate code. Currently, TypeCheckPattern.cpp essentially converts let a > = opt1 into case let a? = opt1; if this proposal is accepted, it should > similarly convert let (a, b) = (opt1, opt2) into case let (a?, b?) = (opt1, > opt2). > > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#edge-cases>Edge > cases > > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#nested-tuples-of-optionals>Nested > tuples-of-optionals > > Permitting deeper pattern matching of nested tuples is highly precedented by > pattern matching, but is a niche feature. It should be supported if easily > achievable. > > guard let (a, (b, c)) = (opt1, (opt2, opt3)) else { ... } > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#expressions-returning-tuples-of-optionals>Expressions > returning tuples of optionals > > Ideally, optional bindings whose initializer is an expression evaluating to a > tuple of optionals would be supported: > > let tuple = (opt1, opt2) > if let (a, b) = tuple { ... } > However, I'm not sure if Swift will have pinned down the type of the > initializer at the point where it's generating the pattern. If this would be > difficult or impossible to implement, Swift should continue to interpret code > like this as attempting to bind an optional tuple, rather than a tuple of > optionals. > > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#single-name-patterns>Single-name > patterns > > In theory, Swift could allow you to bind a tuple of optionals to a single > constant: > > if let tuple = (opt1, opt2) { ... } > However, this seems error-prone; the pattern doesn't draw a very clear > picture of the value being operated upon, so you could easily misinterpret it > as binding an optional tuple. Because of this ambiguity, Swift should always > interpret this construct as binding an optional tuple, rejecting it with a > type error if necessary. > > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#impact-on-existing-code>Impact > on Existing Code > > This proposal is additive compared to SE-0099, but in combination with it, > essentially replaces the Swift 2.2 compound binding syntax with a different, > incompatible one. When moving directly from Swift 2.2, the migrator should > convert old-style compound optional binding clauses: > > guard let a = opt1, b = opt2, c = opt3 else { ... } > Into the new, tuple-based ones: > > guard let (a, b, c) = (opt1, opt2, opt3) else { ... } > The "one-let-per-binding" syntax remains compatible with both Swift 2.2 and > Swift 3, so projects which must support both can still perform multiple > optional bindings in a single if statement without resorting to an #if > swift(>=3.0) build configuration: > > guard let a = opt1, let b = opt2, let c = opt3 else { ... } > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#alternatives-considered>Alternatives > Considered > > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#not-accepting-this-proposal>Not > accepting this proposal > > This proposal does not add new functionality; it merely removes keyword > clutter. However, it offers a convenient replacement for a commonly-used > feature which has just been removed as a result of grammatical ambiguity, not > user confusion or lack of utility. > > > <https://gist.github.com/brentdax/46c340c967358589ade5351531ac8920#providing-similar-standard-library-functionality>Providing > similar standard library functionality > > Rather than including this functionality in the compiler, the standard > library could provide a series of functions like: > > public func all<T, U>(_ t: T?, _ u: U?) -> (T, U)? { ... } > public func all<T, U, V>(_ t: T?, _ u: U?, _ v: V?) -> (T, U, V)? { ... } > // etc. > These could then be used in a similar fashion to this proposal: > > guard let (a, b, c) = all(opt1, opt2, opt3) else { ... } > However, because we do not have variadic generics, we would need to provide a > set of overloads for different arities, and our support would be limited to > the arities we chose to provide. (Support for tuples, as opposed to separate > parameters, would require a second set of overloads). Meanwhile, the tuple > matching syntax is already precedented in case conditionals, so extending it > seems pretty natural. Providing this in the compiler seems like the right > solution. > > > -- > Brent Royal-Gordon > Architechies >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution