<div dir="ltr"><div>That's a useful pattern, but the implementation above creates a function that has both a return value and a side effect, which is likely to be unexpected for many readers. </div><div><br></div><div>public func replace<T>(inout a: T?, with b: T?, andCleanOldValue clean:T->()) { ... }</div><div><br></div><div>replace(&prop, with: newValue) { oldValue in</div><div> oldValue.clean()</div><div>}</div><div><br></div><div>As a bonus one can automatically unwrap nil.</div><div><br></div><div>Although in real life I tend to move this logic to property accessors, e.g.</div><div><br></div><div>// Currently executing task. This property manages task state.</div><div><br></div><div>var task: NSURLSessionTask? { </div><div> willSet { task?.cancel() } </div><div> didSet { task?.resume() }</div><div>}</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 14, 2015 at 7:59 AM, Dave Abrahams via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><span class=""><blockquote type="cite"><div>On Dec 13, 2015, at 2:21 PM, Kevin Ballard via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br><div>
<div><div>A function I find myself defining in a lot of my projects looks like the following:<br></div>
<div> </div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">/// Replace the value of `a` with `b` and return the old value.<br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">public func replace<T>(inout a: T, with b: T) -> T {<br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif"> var value = b<br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif"> swap(&a, &value)<br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif"> return value<br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">}<br></span></div>
<div> </div>
<div>This is a pretty simple function, and useful in a wide variety of circumstances, so I'd love to get it into the standard library. It doesn't actually enable any behavior that wasn't previously possible, but it does shrink some common code patterns, and I find the shorter code easier to read.<br></div>
<div> </div>
<div>An example of a place where I use it often is in replacing an optional property with a new value (or with nil) and cleaning up the previous value. Assuming a property like<br></div>
<div> </div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">var task: NSURLSessionTask?<br></span></div>
<div> </div>
<div>This replaces<br></div>
<div> </div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">if let task = self.task {<br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif"> task.cancel()<br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">}<br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">task = nil<br></span></div>
<div> </div>
<div>with<br></div>
<div> </div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">replace(&task, with: nil)?.cancel()<br></span></div>
<div> </div>
<div>Or sometimes I use it like<br></div>
<div> </div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">if let value = replace(&prop, with: newValue) {</span><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif"><br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif"> // multi-line cleanup</span><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif"><br></span></div>
<div><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif">}</span><span style="font-family:menlo,consolas,"courier new",monospace,sans-serif"><br></span></div>
<div> </div>
<div>This is particularly nice if it's a COW value that I want to mutate, as it means I don't have to worry about getting unwanted copies due to the property still holding the old value while I muck with it.<br></div></div></div></blockquote><div><br></div></span><div>This is a generalization of the postincrement pattern (mutate a value and return the original) and given that we're moving away from that I'm not sure it's something we want to enshrine in the standard library. That said, here's a question: looking at your use cases, how many of them are using something other than nil (or some moral equivalent) as the second argument? If this is effectively a non-destructive move in nearly all cases, I'd rather support that more directly.</div><div><br></div><div>If cases other than "nondestructive move" are common <u>enough</u>, I'd consider something like this syntax instead:</div><div><br></div><div> (task <- nil).cancel()</div><div><br></div><div>But I strongly suspect this isn't a common enough pattern to warrant introducing an operator.</div><span class=""><div><br></div><blockquote type="cite"><div>
<div>Question: For trivial backwards-compatible API changes like this, does a proposal PR need to be submitted to the swift-evolution repo, or is discussion on this ML sufficient before submitting a patch?</div></div></blockquote><br></span>A proposal is needed for all new/changed API.</div><div><br></div><div>-Dave</div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=1p9Jer2O6jVE9KWvo-2B9iUaEyN8slp4IizyiLwsfp54OZXZs-2Bll1DicftS07fy3Z8pki5ncqRo9ycGwxqoCngq0JZlTJ4VDpqHr1So-2BBTPULnx-2FqGqyOd5NaZDA8xyuZezEmmts05xItH8SxttnvPDnRyeHrNQPKcg1rl5K3ftbALE6bdqd9dsPlSAssYoupbWZ5hPzBl8fpweqq9hg18Rj1ipqbuVvhhkmi72exv0Gc-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
</div>
<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">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>
<br></blockquote></div><br></div>