<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I tend to agree with David here: there’s a lot more confusion inherent in a “var” parameter than “if var.”</div><div class=""><br class=""></div><div class="">P</div><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 24, 2016, at 10:58 AM, David Owens II via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class="">Removing var from function params, I get that. But the if-binding is unfortunate. It's literally a line of code for the sole purpose of making the compiler happy. </div><div class=""><br class=""></div><div class="">Working with optionals is already clumsy enough, we really don't need to make it more so. <br class=""><br class="">-David</div><div class=""><br class="">On Jan 23, 2016, at 5:03 AM, J. Cheyo Jimenez via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class=""><div class=""><font size="2" class=""><span style="background-color:rgba(255,255,255,0)" class="">if let currentRect = selection?.rect {</span></font></div><div class=""><font size="2" class=""><span style="background-color:rgba(255,255,255,0)" class=""> var expandedRect = currentRect </span></font></div></div><div class=""><font size="2" class=""><span style="background-color:rgba(255,255,255,0)" class=""><br class=""></span></font></div><div class=""><font size="2" class=""><span style="background-color:rgba(255,255,255,0)" class="">VS</span></font></div><div class=""><font size="2" class=""><span style="background-color:rgba(255,255,255,0)" class=""><br class=""></span></font></div><div class=""><div class=""><font size="2" class=""><span style="background-color:rgba(255,255,255,0)" class="">if var expandedRec = selection?.rect {</span></font></div></div><div class=""><br class=""></div>If let is perfectly fine if most of the code base is with classes. Perhaps I can see the argument on why pattern matching and even why functions should only allow let but for guard and if binding, the uses of var are more practical and less boiler plate <span class=""></span>specially when dealing with mutable value types. <br class=""><br class="">On Saturday, January 23, 2016, Marc Knaup via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="">Scanning through our iOS project with ~600 Swift files we barely use `var` for function parameters or for if/guard statements.<div class=""><br class=""></div><div class="">I think the problems you outline should not be solved by using `var` but by making the code's intent much clearer by using distinct variable names.</div><div class=""><br class=""></div><div class="">In your example it is not clear what the purpose of the shadowed `rect` variable is. The same is true if you use `if var rect = …`:</div><div class=""><br class=""></div><div class=""><div class=""><font face="monospace, monospace" class="">var selection = getRectangularSelection()</font></div><div class=""><font face="monospace, monospace" class="">if let rect = selection?.rect {</font></div><div class=""><font face="monospace, monospace" class=""> var rect = rect // what is rect used for? the variable name is quite generic</font></div><div class=""><font face="monospace, monospace" class=""> // mutate `rect` ...</font></div><div class=""><div class=""><font face="monospace, monospace" class=""> // probably a lot of code</font></div><div class=""><font face="monospace, monospace" class=""> // …</font></div></div><div class=""><font face="monospace, monospace" class=""><br class=""></font></div><div class=""><font face="monospace, monospace" class=""> selection.rect = rect // what rect again?</font></div><div class=""><font face="monospace, monospace" class="">}</font></div></div><div class=""><br class=""></div><div class="">A better solution is to name the variables differently and make their intent very clear:</div><div class=""><br class=""></div><div class=""><div class=""><font face="monospace, monospace" class="">var selection = getRectangularSelection()</font></div><div class=""><font face="monospace, monospace" class="">if let currentRect = selection?.rect {</font></div><div class=""><font face="monospace, monospace" class=""> var expandedRect = currentRect // intent becomes clear now</font></div><div class=""><font face="monospace, monospace" class=""> // expand `expandedRect` ...</font></div><div class=""><font face="monospace, monospace" class=""> // probably a lot of code</font></div><div class=""><font face="monospace, monospace" class=""> // …</font></div><div class=""><font face="monospace, monospace" class=""> </font></div><div class=""><font face="monospace, monospace" class=""> selection.rect = expandedRect // ah, THAT rect!</font></div><div class=""><font face="monospace, monospace" class="">}</font></div></div><div class=""><br class=""></div><div class="">So `if var` is really not necessary and causes more harm than good due to reduced clarity.</div><div class=""><br class=""></div><div class="">-1 for reversing the proposal from me.</div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Fri, Jan 22, 2016 at 6:26 PM, David Farler via swift-evolution <span dir="ltr" class=""><<a href="javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');" target="_blank" class="">swift-evolution@swift.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello everyone,<br class="">
<br class="">
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.<br class="">
<br class="">
There are two main patterns that the removal penalizes:<br class="">
<br class="">
- Get-Modify-Reassign<br class="">
- Get-Modify-Return<br class="">
<br class="">
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.<br class="">
<br class="">
I've seen a few common responses to the var removal. Consider a `Rectangle` struct:<br class="">
<br class="">
<br class="">
struct Rectangle {<br class="">
var origin: (x: Double, y: Double)<br class="">
var size: (width: Double, height: Double)<br class="">
}<br class="">
<br class="">
<br class="">
Even with mutable variables `origin` and `size`, this pattern would be impossible:<br class="">
<br class="">
<br class="">
var selection = getRectangularSelection()<br class="">
if var rect = selection?.rect {<br class="">
// Mutate `rect` ...<br class="">
selection.rect = rect<br class="">
}<br class="">
<br class="">
<br class="">
So, one might shadow the variable, which is not ideal:<br class="">
<br class="">
<br class="">
var selection = getRectangularSelection()<br class="">
if let rect = selection?.rect {<br class="">
var rect = rect // Not so great<br class="">
// Mutate `rect` ...<br class="">
selection.rect = rect<br class="">
}<br class="">
<br class="">
<br class="">
Or, you might make a transformation function on `Rect`:<br class="">
<br class="">
<br class="">
struct Rectangle {<br class="">
var origin: (x: Double, y: Double)<br class="">
var size: (width: Double, height: Double)<br class="">
func withOrigin(x: Double, y: Double) -> Rect {<br class="">
var r = self<br class="">
r.origin = (x, y)<br class="">
return r<br class="">
}<br class="">
}<br class="">
<br class="">
<br class="">
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:<br class="">
<br class="">
<br class="">
if let rect = selection?.rect.with(origin: newOrigin) {<br class="">
// ...<br class="">
}<br class="">
<br class="">
<br class="">
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.<br class="">
<br class="">
These problems come up with the other variable bindings but the one that ended up bothering me the most was `guard var`:<br class="">
<br class="">
<br class="">
func transform(selection: Rect?) {<br class="">
guard let rect = selection else { return }<br class="">
var _rect = rect<br class="">
// Mutate `_rect` ...<br class="">
}<br class="">
<br class="">
<br class="">
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.<br class="">
<br class="">
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.<br class="">
<br class="">
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.<br class="">
<br class="">
Regards,<br class="">
David<br class="">
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote></div><br class=""></div>
</blockquote>
</div></blockquote><blockquote type="cite" class=""><div class=""><span class="">_______________________________________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class=""></div></blockquote></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>