[swift-evolution] Reconsidering SE-0003 Removing var from Function Parameters and Pattern Matching

Dave Abrahams dabrahams at apple.com
Thu Jan 28 16:07:52 CST 2016


on Thu Jan 28 2016, Kevin Ballard <swift-evolution at swift.org> wrote:

> Oh man, huge +1 from me here.
>
> Apparently I never actually read that proposal. I was under the
> impression it only removed var from function parameters. And while I
> find that mildly annoying, I was ok with it because of the argument
> for removing as many keywords as possible from function parameter
> lists (e.g. to open up those keywords to be used as external parameter
> names). Though I'd really prefer to keep var anyway.
>
> But I didn't realize until now that it also prohibits `var` from _all_
> pattern matching, such as if-let, guard-let, etc. And I find that
> incredibly restrictive. I am not ok at all with that restriction. It
> makes no sense to me, and it makes a lot of very clean code become
> much messier by the addition of completely spurious `var foo = foo`
> lines everywhere. What's more, you can't even add lines like that
> everywhere because of Swift's prohibition from shadowing variables
> from the same scope (e.g. you can't shadow the variable bound from
> `guard let` because it's in the same scope).
>
> I see Dave Abrahams arguing that this feature is tripping some people
> up. 

I'm really making others' arguments for them here.  It is a fact that it
has tripped some people up.  I still don't support removing it.

> But I don't see that as appropriate grounds for removing it from the
> language. If people don't understand `if var` or `for var x in` then
> they can just not write code that uses that feature. And if the
> argument is that people might have to read other code that uses that,
> well, there's plenty of stuff in Swift that you have to actually learn
> about before you can understand how it works, and using `var` in
> patterns does not seem like one of the trickiest things. And if the
> confusion stems from not understanding the difference between `var`
> and `inout`, I don't see how preventing someone from writing `if var`
> will solve that confusion, because the same person would presumably
> have the same confusion about `var foo = bar`.
>
> -Kevin Ballard
>
> On Fri, Jan 22, 2016, at 09:26 AM, David Farler via swift-evolution wrote:
>> Hello everyone,
>> 
>> I'd like to reconsider SE-0003 for Swift 3 and propose cancelling the change in its entirety. After collecting feedback since Swift's open source launch, I no longer feel this is a good move and there are a few reasons why.
>> 
>> There are two main patterns that the removal penalizes:
>> 
>> - Get-Modify-Reassign
>> - Get-Modify-Return
>> 
>> I've found that many of the problems with this proposal stem from the uses before and after the "Modify" part, before returning or reassigning with the new value.
>> 
>> I've seen a few common responses to the var removal. Consider a `Rectangle` struct:
>> 
>> 
>> struct Rectangle {
>>  var origin: (x: Double, y: Double)
>>  var size: (width: Double, height: Double)
>> }
>> 
>> 
>> Even with mutable variables `origin` and `size`, this pattern would be impossible:
>> 
>> 
>> var selection = getRectangularSelection()
>> if var rect = selection?.rect {
>>  // Mutate `rect` ...
>>  selection.rect = rect
>> }
>> 
>> 
>> So, one might shadow the variable, which is not ideal:
>> 
>> 
>> var selection = getRectangularSelection()
>> if let rect = selection?.rect {
>>  var rect = rect // Not so great
>>  // Mutate `rect` ...
>>  selection.rect = rect
>> }
>> 
>> 
>> Or, you might make a transformation function on `Rect`:
>> 
>> 
>> struct Rectangle {
>>  var origin: (x: Double, y: Double)
>>  var size: (width: Double, height: Double)
>>  func withOrigin(x: Double, y: Double) -> Rect {
>>    var r = self
>>    r.origin = (x, y)
>>    return r
>>  }
>> }
>> 
>> 
>> This is a much better solution than shadowing but you would need one of these for any property that you want to mutate and I think you'll agree that it doesn't scale with the language we have today. This response begs for a kind of initializer that takes all of the fields of the original struct except any that you want to override:
>> 
>> 
>> if let rect = selection?.rect.with(origin: newOrigin) {
>>  // ...
>> }
>> 
>> 
>> Straw syntax, but maybe you'll see something along these lines on swift-evolution in the future, which would provide a clear alternative to direct mutation patterns. Even then, I think having complementary patterns in the language isn't a bad thing.
>> 
>> These problems come up with the other variable bindings but the one that ended up bothering me the most was `guard var`:
>> 
>> 
>> func transform(selection: Rect?) {
>>  guard let rect = selection else { return }
>>  var _rect = rect
>>  // Mutate `_rect` ...
>> }
>> 
>> 
>> One of the guard statement's main purposes is to conditionally bind a value as a peer in its own scope, not an inner scope like if statements. Not having var makes the guard statement much weaker.
>> 
>> There is certainly a bit of confusion about the nuances between value and reference semantics, who owns a value and when, how effects are propagated back to values, but I think we can attack the problem with more finesse.
>> 
>> Value types are one of the attractive features of Swift – because of their semantics, mutating algorithms are written in a familiar style but keeping effects limited to your unique reference. I don't think we should give that up now to address confusion about semantics, out of principle, or in anticipation of new language features. I propose cancelling this change for Swift 3 and continue to allow `var` in the grammar everywhere it occurs in Swift 2.2.
>> 
>> Regards,
>> David
>> _______________________________________________
>> 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

-- 
-Dave



More information about the swift-evolution mailing list