<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Just some alternate naming suggestions for with() and withVar(), as the naming guidelines suggest -ed/-ing:</div><div class=""><br class=""></div><div class=""><i class="">withVar</i></div><div class="">altered() // Changes a value copy / reference and returns it</div><div class="">mutated() // Or this, but uses value-specific term ‘mutate’</div><div class=""><br class=""></div><div class=""><div class=""><i class="">with</i></div><div class="">inspect() // Works with an immutable copy, has @discardableResult</div><div class="">use()</div></div><div class=""><br class=""></div><br class=""><blockquote type="cite" class="">On 28 May 2016, at 10:19 AM, Brent Royal-Gordon via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">- A plain `with` whose closure parameter is not mutable and which is marked `@discardableResult`.<br class=""></blockquote><br class="">I would like to see this version restricted to AnyObject. It has extremely limited utility with value types. It would usually be a mistake to call it with a value type.<br class=""></blockquote><br class="">I would not. It gives you a way to give a value type a short, scoped, immutable alias:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>with(RareMagicalDeviceOwner.shared.spimsterWickets[randomIndex]) {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>print($0.turns)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>print($0.turnSpeed)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}<br class=""><br class="">And in this form, there is no danger of mistakenly mutating the value type, because mutating methods would not be allowed:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>with(RareMagicalDeviceOwner.shared.spimsterWickets[randomIndex]) {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>$0.turnRepeatedly(times: 3)<span class="Apple-tab-span" style="white-space:pre">        </span>// Error: can't call mutating method on immutable parameter<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}<br class=""><br class="">To be clear, I'm not convinced there's a need to make any change from the proposed version at all. I'm spitballing alternate designs here, trying to see if there might be something a little better out there. But so far, I think the proposal balances the feature size against strictness pretty well, whereas these stricter designs I'm discussing increase the surface of the feature more than they improve it. This is a small (but significant!) convenience, and I feel pretty strongly that it should have a small implementation.<br class=""><br class=""><blockquote type="cite" class="">That said, I am not convinced these non-copying functions would be worth having after method cascades are introduced. Are there any use cases left for them in that future?<br class=""></blockquote><br class="">Yes, absolutely. Method cascades have a narrow use case: methods on `self`. Not everything in Swift is a method, and not all methods are on `self`.<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>with(tableView.cellForRow(at: indexPath).myLabel) { label in<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>print("Constraining label: \(label)")<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>NSLayoutConstraint.activate(<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>NSLayoutConstraint.withVisualFormat("|-[label]-|", options: [], metrics: [:], views: ["label": label]) +<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>NSLayoutConstraint.withVisualFormat("V:|[label]|", options: [], metrics: [:], views: ["label": label])<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>constrainedLabels.append(label)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}<br class=""><br class="">None of the calls in that `with` block would benefit from method cascades, but they all benefit from `with`.<br class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">- A `withVar` whose parameter *is* mutable and which is *not* marked `@discardableResult`. (This would help with the fact that our use of `@discardableResult` is a little dangerous, in that people might expect mutations to affect the original variable even if it's a value type.)<br class=""><br class="">`withVar` does, I think, make it pretty clear that you're working with a copy of the variable.<br class=""></blockquote><br class="">One thing to consider in choosing a name here is the cases where this function would still be useful in a future that includes method cascades. The one thing this function does that method cascades don’t is make a copy of the value before operating on it and returning it. <br class=""><br class="">With that in mind, I think it is worthwhile to consider the name `withCopy` and make the closure argument optional.<br class=""></blockquote><br class="">I specifically considered and rejected `withCopy` because it only creates a copy of a value type, not a reference type. (Of course, it does create a copy of the reference itself, but that's a very subtle distinction.) I chose `withVar` to make it very clear that you're getting the same semantics as you would for a `var` temporary.<br class=""><br class=""><blockquote type="cite" class="">public func withCopy<T>(_ item: T, update: (@noescape (inout T) throws -> Void)?) rethrows -> T {<br class=""> var this = item<br class=""> try update?(&this)<br class=""> return this<br class="">}<br class=""><br class="">This function would be more clear and useful in conjunction with method cascades:<br class=""><br class="">let bar = withCopy(foo)<br class=""> ..cascaded = “value"<br class=""> ..operations()<br class=""> ..onFoo()<br class=""></blockquote><br class="">Honestly, I'm not sure there's a coherent way to make method cascades work with your `withCopy` (or the `copy` function you mentioned upthread) at all.<br class=""><br class="">Here's the problem. Suppose you have a property like this:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>var array: [Int]<br class=""><br class="">And then you write this:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>array = [1, 2, 3]<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>return array<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>..remove(at: 1)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>..remove(at: 0)<br class=""><br class="">I assume you think this should not only *return* `[3]`, but also *set* `array` to `[3]`. That's kind of implied by the fact that you think we need a `withCopy(array)` call to protect `array` from being affected by these calls.<br class=""><br class="">But that means that in this version:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>array = [1, 2, 3]<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>return withCopy(array)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>..remove(at: 1)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>..remove(at: 0)<br class=""><br class="">You are trying to call `mutating` methods on an *immutable* value, the return value of `withCopy`. Normally, the compiler would reject that.<br class=""><br class="">Perhaps you could say that method cascades operate on a copy if the receiver is immutable, but that makes code vague and its behavior subtle and easily changed by accident. For instance, if a property is `internal private(set)`, then moving a method cascade from code which can't see the setter to code which can would silently change the code from immutable to mutable. Similarly, adding the `private(set)` would not cause the code which previously modified it to produce an error; it would instead silently change to no longer mutate where it used to before. That's not acceptable behavior from a language feature.<br class=""><br class="">About the only solution to this I can come up with is to make `withCopy` have an `inout` return. But this at best forms an attractive nuisance: If you use normal `mutating` method calls instead of method cascading, your changes are going to disappear into the ether. And depending on how `inout` returns are actually implemented, it could lead to worse misbehavior.<br class=""><br class="">-- <br class="">Brent Royal-Gordon<br class="">Architechies<br class=""><br class="">_______________________________________________<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=""></blockquote><br class=""></body></html>