Just some alternate naming suggestions for with() and withVar(), as the naming guidelines suggest -ed/-ing:
withVar altered() // Changes a value copy / reference and returns it mutated() // Or this, but uses value-specific term ‘mutate’ with inspect() // Works with an immutable copy, has @discardableResult use() > On 28 May 2016, at 10:19 AM, Brent Royal-Gordon via swift-evolution > <swift-evolution@swift.org> wrote: > >>> - A plain `with` whose closure parameter is not mutable and which is marked >>> `@discardableResult`. >> >> 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. > > I would not. It gives you a way to give a value type a short, scoped, > immutable alias: > > with(RareMagicalDeviceOwner.shared.spimsterWickets[randomIndex]) { > print($0.turns) > print($0.turnSpeed) > } > > And in this form, there is no danger of mistakenly mutating the value type, > because mutating methods would not be allowed: > > with(RareMagicalDeviceOwner.shared.spimsterWickets[randomIndex]) { > $0.turnRepeatedly(times: 3) // Error: can't call mutating > method on immutable parameter > } > > 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. > >> 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? > > 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`. > > with(tableView.cellForRow(at: indexPath).myLabel) { label in > print("Constraining label: \(label)") > > NSLayoutConstraint.activate( > NSLayoutConstraint.withVisualFormat("|-[label]-|", > options: [], metrics: [:], views: ["label": label]) + > NSLayoutConstraint.withVisualFormat("V:|[label]|", > options: [], metrics: [:], views: ["label": label]) > ) > > constrainedLabels.append(label) > } > > None of the calls in that `with` block would benefit from method cascades, > but they all benefit from `with`. > >>> - 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.) >>> >>> `withVar` does, I think, make it pretty clear that you're working with a >>> copy of the variable. >> >> 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. >> >> With that in mind, I think it is worthwhile to consider the name `withCopy` >> and make the closure argument optional. > > 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. > >> public func withCopy<T>(_ item: T, update: (@noescape (inout T) throws -> >> Void)?) rethrows -> T { >> var this = item >> try update?(&this) >> return this >> } >> >> This function would be more clear and useful in conjunction with method >> cascades: >> >> let bar = withCopy(foo) >> ..cascaded = “value" >> ..operations() >> ..onFoo() > > 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. > > Here's the problem. Suppose you have a property like this: > > var array: [Int] > > And then you write this: > > array = [1, 2, 3] > return array > ..remove(at: 1) > ..remove(at: 0) > > 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. > > But that means that in this version: > > array = [1, 2, 3] > return withCopy(array) > ..remove(at: 1) > ..remove(at: 0) > > You are trying to call `mutating` methods on an *immutable* value, the return > value of `withCopy`. Normally, the compiler would reject that. > > 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. > > 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. > > -- > Brent Royal-Gordon > Architechies > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution