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

Dave Abrahams dabrahams at apple.com
Tue Jan 26 18:41:01 CST 2016


on Tue Jan 26 2016, Tian Zhang <swift-evolution at swift.org> wrote:

> I’m also curious how most people fix “guard var” or “if var”?
> Especially for checking a class object for protocol conformation and
> set variable on the object?
>
> like in this case,
>
>> if var vc = vc as? ControlPanelConfigurationProtocol {
>>         vc.servicePresentationObject = service
>>         vc.presentAsPanel = true
>> }
>
> become
>
>> if let vc = vc as? ControlPanelConfigurationProtocol {
>>         var vc = vc
>> 
>>         vc.servicePresentationObject = service
>>         vc.presentAsPanel = true
>> }


If vc has class type, you don't need the var at all.

> I saw a few people suggest to create a method on the protocol like
> “configureObject(...)” with all potential args and have the object to
> figure it out but doing so I feel we’re losing the benefits offered by
> property observation for the underlying object. Using pattern “if let”
> with a “var” in the block just to make the property mutable again
> feels really strange.
>
> Best Wishes,
> Tian
>> An alternative would certainly be interesting but I would prefer to
>> take it one step at a time and avoid being hasty so we can come up
>> with something really great. What did most of your var fixes look
>> like, by the way? Did you end up changing the layout of your value
>> types or did you decide to add more vars?
>> 
>> David
>> 
>> > On Jan 24, 2016, at 7:19 PM, Zach Waldowski via swift-evolution
>> > <swift-evolution at swift.org
>> > <https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote:
>> > 
>> > -1
>> > 
>> > Having already adopted the syntax in my projects in anticipation of 2.2,
>> > the increase in clarity at the expense of terseness is appreciated. A
>> > proposal should not be discussing an alternative, not a rollback.
>> > 
>> > Cheers!
>> > Zachary Waldowski
>> > zach at waldowski.me <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> > 
>> > On Fri, Jan 22, 2016, at 12:26 PM, 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>
>> >> 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>
>> > 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

-- 
-Dave



More information about the swift-evolution mailing list