+1 for the reversal. Removing var introduces inconsistencies. I never use var in these contexts, but it&#39;s good to have the option.<br><div class="gmail_quote"><div dir="ltr">On Fri, Jan 22, 2016 at 1:27 PM Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><blockquote type="cite"><div>On Jan 22, 2016, at 10:21 AM, David Farler &lt;<a href="mailto:dfarler@apple.com" target="_blank">dfarler@apple.com</a>&gt; wrote:</div><br><div><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><br>On Jan 22, 2016, at 9:45 AM, Joe Groff &lt;<a href="mailto:jgroff@apple.com" target="_blank">jgroff@apple.com</a>&gt; wrote:</div><br><div><blockquote type="cite" style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br>On Jan 22, 2016, at 9:26 AM, David Farler via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br>Hello everyone,<br><br>I&#39;d like to reconsider SE-0003 for Swift 3 and propose cancelling the change in its entirety. After collecting feedback since Swift&#39;s open source launch, I no longer feel this is a good move and there are a few reasons why.<br><br>There are two main patterns that the removal penalizes:<br><br>- Get-Modify-Reassign<br>- Get-Modify-Return<br><br>I&#39;ve found that many of the problems with this proposal stem from the uses before and after the &quot;Modify&quot; part, before returning or reassigning with the new value.<br><br>I&#39;ve seen a few common responses to the var removal. Consider a `Rectangle` struct:<br><br><br>struct Rectangle {<br>var origin: (x: Double, y: Double)<br>var size: (width: Double, height: Double)<br>}<br><br><br>Even with mutable variables `origin` and `size`, this pattern would be impossible:<br><br><br>var selection = getRectangularSelection()<br>if var rect = selection?.rect {<br>// Mutate `rect` ...<br>selection.rect = rect<br>}<br></blockquote><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">These examples don&#39;t make sense to me. None of them mutate the &#39;if var rect&#39; binding at all. Are you sure this is what you meant?</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">I abbreviated there with // Mutate `rect.</div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>Ah, sorry, missed that. Years of bad documentation have trained my brain to blank out comments.</div></div></div><div style="word-wrap:break-word"><div><div><br></div><div>-Joe</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><blockquote type="cite" style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">So, one might shadow the variable, which is not ideal:<br><br><br>var selection = getRectangularSelection()<br>if let rect = selection?.rect {<br>var rect = rect // Not so great<br>// Mutate `rect` ...<br>selection.rect = rect<br>}<br><br><br>Or, you might make a transformation function on `Rect`:<br><br><br>struct Rectangle {<br>var origin: (x: Double, y: Double)<br>var size: (width: Double, height: Double)<br>func withOrigin(x: Double, y: Double) -&gt; Rect {<br> var r = self<br> r.origin = (x, y)<br> return r<br>}<br>}<br><br><br>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&#39;ll agree that it doesn&#39;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><br><br>if let rect = selection?.rect.with(origin: newOrigin) {<br>// ...<br>}<br></blockquote><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">You can approximate this today without any new language features:</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">protocol Updatable {}</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">extension Updatable {</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important"> func with&lt;T&gt;(change: (inout T) -&gt; ()) -&gt; T {</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">   var update = value</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">   change(&amp;update)</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">   return update</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important"> }</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">}</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">if let rect =  selection?.rect.with { $0.origin = newOrigin } {</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">}</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">I think this approach generally leads to cleaner code, since it&#39;s not forcing you to bind names to otherwise uninteresting intermediate values.</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">It&#39;s definitely more explicit but I don&#39;t know if I agree that it&#39;s cleaner with respect to the mutations themselves – it has a lot of the same shape. I also worry about performance with this pattern as is.</div><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><blockquote type="cite" style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Straw syntax, but maybe you&#39;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&#39;t a bad thing.<br><br>These problems come up with the other variable bindings but the one that ended up bothering me the most was `guard var`:<br><br><br>func transform(selection: Rect?) {<br>guard let rect = selection else { return }<br>var _rect = rect<br>// Mutate `_rect` ...<br>}<br><br><br>One of the guard statement&#39;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><br>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><br>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&#39;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></blockquote><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">I disagree. We have a lot of evidence that &#39;if var&#39; confuses people—a lot of users think that &#39;if var&#39; and &#39;var&#39; bindings in case patterns will write back to the original value when this isn&#39;t the case. Classes make this worse, since &#39;if var&#39; *will* seem to work that way when projecting through optional class references, and the value vs reference semantics divide is confusing enough as it is.<span> </span></span></div></blockquote><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">I totally agree that the subtlety of the semantics easily gets lost but I think we can come up with better ways to make them clearer without blowing away a whole class of syntax. I see this confusion as more of a holistic indictment of how we express the semantics rather than just the syntax of `var`. I just don&#39;t feel like removing this now is a slam dunk.</div><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><blockquote type="cite" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">Those of us who do understand the semantics don&#39;t save anything either—I at least have to mentally audit any code I see using &#39;if var&#39; to ensure that writeback wasn&#39;t intended by the original author. Code is read and maintained more often than it&#39;s written, and it&#39;s written by more novices than experts, and &#39;if var&#39; and its friends feel like very expert-writer-centric features to me.</span><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">-Joe</span></div></blockquote></div></blockquote></div></div>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div>