[swift-evolution] Obsoleting `if let`

Austin Zheng austinzheng at gmail.com
Wed Feb 3 22:21:58 CST 2016


I agree with Jonathan; furthermore, Swift already puts aside 'principled behavior' in favor of pragmatically giving Optional special treatment in quite a few other ways, none of which have bothered people as much as 'if let'.

My question is, what's the advantage any such change is going to provide in exchange for the inevitable costs of broken code and programmer friction? Is it going to prevent or reduce a commonly-made mistake, or add expressivity to the language? Is it going to allow the compiler to generate better code? Is it necessary to lay the foundation for future features? In my opinion, a slight increase in orthogonality is not really a good enough justification.

Austin


> On Feb 3, 2016, at 8:03 PM, Jonathan Tang via swift-evolution <swift-evolution at swift.org> wrote:
> 
> FWIW, I don't see any problems with the current "if let x = ... " syntax or behavior.  I view it as a mainstream language finally implementing anaphoric-if (as described in Paul Graham's _On Lisp_), and the unwrapping seems like a natural consequence of the semantics, because what else *could* it do?  The if-statement needs to test on something; it seems natural to me that the if tests for optional == nil, and then the let binds the payload of the optional if it matches.
> 
> I wouldn't rule out there being something better, but I'm -1 on all the proposals I've seen so far to change it.
> 
> On Wed, Feb 3, 2016 at 7:49 PM, Taras Zakharko via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> I already suggested this in the bind thread but I guess it was either not interesting or people missed it, so here it goes again :)
> 
> What about changing the syntax of optional binding such that the optional unwrapping becomes explicit? I.e. instead of 
> 
>   if let x = some_optional { }
> 
> one writes
> 
>   if let x = some_optional! { }
> 
> Essentially, the point of this suggestion is that the runtime error generated by unwrapping an empty Optional is instead treated as condition failure in a conditional statement. While there is some typing overhead over the current syntax, I see a number of potential benefits of this approach:
> 
>  1. It is in line with the current semantics and syntax of optional unwrapping (does not introduce any new syntagm)
>  2. It makes the unwrapping operation explicit (thus addressing the basic criticism from the bind discussion)
>  3. It frees variable declaration of the contextual polisemy (i.e. let and var have the same semantics as nowhere else, there is no ‘unwrapping’ magic)
>  4. The change is minimal compare to what we have now and can be easily ported automatically
> 
> Potential issues:
> 
>  1. One character typing overhead — but I dot think that should matter. I always had the impression that Swift favours clarity over compactness (which is a good thing IMO)
>  2. it allows syntactic ambiguity with optional chaining. E.g. if let x = a.b?.c! { } and if let x = a.b!.c would have the same meaning. Then again, this ambiguity already exits in the language to begin with. 
> 
> — Taras
> 
>> On 04 Feb 2016, at 01:25, Chris Lattner via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>>> 
>>> On Feb 3, 2016, at 3:47 PM, Jordan Rose via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> Data point (which Chris brought up already, I think?): We tried this* and got a lot of negative feedback. Optionals are unwrapped too often for people to be comfortable writing "if let name? = optionalCondition”.
>> 
>> Yes, I even implemented this and it was in the compiler for awhile, then later ripped it back out.  You can find the history in git.  I would guess that this all happened in ~March 2015.
>> 
>> -Chris
>> 
>>> 
>>> It may be more uniform and even more pedantically correct, but our users hated it.
>>> 
>>> Jordan
>>> 
>>> * The actual thing we tried only allowed patterns that began with 'let', but that's close enough.
>>> 
>>> 
>>>> On Feb 3, 2016, at 15:36, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>>> 
>>>> This is a continuation of and alternative proposal to "The bind thread", which seems to have petered out without consensus.
>>>> 
>>>> Currently there are three forms of `if` statement (and `guard` and `while`, but for simplicity I'll just say `if` throughout this discussion):
>>>> 
>>>> 	if booleanCondition
>>>> 	if let name = optionalCondition
>>>> 	if case pattern = expression
>>>> 
>>>> The boolean condition form is fine, but there are flaws in the other two. `if let` is unprincipled and doesn't really say what it does; `if case` is bulky and rarely used.* 
>>>> 
>>>> One very interesting thing about `if case`, too, is that it can actually do optional unwrapping:
>>>> 
>>>> 	if case let name? = optionalCondition
>>>> 
>>>> This avoids the problems with `if let`—it's principled (it comes from a larger language feature) and it explicitly says it's handling optionality—but it still runs up against `if case`'s rarity and wordiness.
>>>> 
>>>> So what I suggest is that we drop the `if let` form entirely and then drop the `case` keyword from `if case`. Pattern-matching conditions can still be distinguished from boolean conditions because boolean conditions can't contain an `=` operator. This, there would now only be two forms of if:
>>>> 
>>>> 	if booleanCondition
>>>> 	if pattern = expression
>>>> 
>>>> And the current `if let` is handled elegantly and clearly by existing pattern-matching shorthand, with only one additional character needed:
>>>> 
>>>> 	if let name? = optionalCondition
>>>> 
>>>> I see two complications with this.
>>>> 
>>>> The first is that, naively, `if let foo = bar` would still be valid, but would have different and vacuous behavior, since the pattern cannot fail to match. The compiler should probably emit an error or at least a warning when this happens.
>>>> 
>>>> The second is our other weird use of the `case` keyword, `for case`, which is now an orphan in the language. I see several ways this could be handled:
>>>> 
>>>> 1. Drop the `for case` functionality entirely; if you want that behavior, use a pattern-matching `if`.
>>>> 2. Replace the loop variable slot in the `for` statement with a pattern. This would force you to put `let` on all simple `for` statements.
>>>> 3. Try to automatically distinguish between simple variables/tuples and patterns in this slot. What could possibly go wrong?
>>>> 4. Require an equals sign before the `in`, like `for let foo? = in optionalFoos`. Looks a little gross, but it's unambiguous.
>>>> 5. Replace `for case` with `for if`, like `for if let foo? in optionalFoos`. This helps flag the unusual conditional behavior of this form of `for`.
>>>> 6. Just keep `for case` and don't worry about the fact that it's not parallel to the other statements anymore.
>>>> 
>>>> Thoughts on any of this?
>>>> 
>>>> 
>>>> 
>>>> * `if case` also has the problem that the `=` isn't appropriate unless you happen to bind some of the data matched by the pattern, but I don't know how to address that. A prior version of this proposal suggested saying `:=` instead of `=`, with the idea that `:=` could become a general pattern-matching operator, but the people I talked over this post with hated that.
>>>> 
>>>> -- 
>>>> Brent Royal-Gordon
>>>> Architechies
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160203/1f00eb6d/attachment.html>


More information about the swift-evolution mailing list