[swift-evolution] [Draft] Tuple-Based Compound Optional Binding

Brent Royal-Gordon brent at architechies.com
Sun Jun 12 19:45:52 CDT 2016

> It takes reaching the last section of the proposal to understand that there is not real issue, that it does not add any functionality, and that it basically amount to stylistic preference for something. It might be more informative to start with that rather than leave it until the end.

You're right; it's quite fair to say that acknowledgement should be moved up front. At the same time, I can better justify why it's not a good solution to the problem.


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. This doesn't conflict with the clause separation syntax because the commas are within parentheses.

In a pinch, this can be used to pattern-match against several optionals:

guard case let (a?, b?, c?) = (opt1, opt2, opt3) else { ... }
However, optional binding is itself redundant in exactly the same way. Optional binding exists because the pattern-matching syntax is too clumsy, and requires too much understanding from the user, for such a common operation. The same concerns apply when performing multiple optional bindings.

Swift's syntax actually permits you to write an optional binding clause analogous to the tuple pattern-match above:

guard let (a, b, c) = (opt1, opt2, opt3) else { ... }
However, Swift does not interpret this as an attempt to bind several optionals inside a tuple; instead it assumes you want to bind and destructure an optional tuple, and type-checking fails because the tuple is not optional.

error: initializer for conditional binding must have Optional type, not 
'(Int?, Int?, Int?)' (aka '(Optional<Int>, Optional<Int>, Optional<Int>)')

Brent Royal-Gordon

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160612/433a2988/attachment.html>

More information about the swift-evolution mailing list