> On May 27, 2016, at 5:12 PM, Brent Royal-Gordon via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
>>> Just mentioning it as to end up... with the proper name for this new 
>>> function.
>> 
>> Naming can always be bikeshedded. 
> 
> One possibility is to split `with` in two:

I much prefer this direction.

> 
> - 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.

If we want a non-copying version that works with value types it should look 
like this:

@discardableResult
public func with<T>(_ item: inout T, use: @noescape (inout T) throws -> Void) 
rethrows {
    try use(&item)
}

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?

> 
> - 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.

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()



> 
>       /// Returns `item` after calling `use` to inspect it.
>       /// 
>       /// If `T` is a value type, `use` is unable to mutate `item`.
>       /// If `T` is a reference type, `use` may use members which 
>       /// change `item`, but cannot assign a different instance.
>       @discardableResult
>       public func with<T>(_ item: T, use: @noescape (T) throws -> Void) 
> rethrows -> T {
>         try use(item)
>         return item
>       }
>       
>       /// Returns `item` after calling `update` to inspect and possibly 
>       /// modify it.
>       /// 
>       /// If `T` is a value type, `update` uses an independent copy 
>       /// of `item`. If `T` is a reference type, `update` uses the 
>       /// same instance passed in, but it can substitute a different 
>       /// instance by setting its parameter to a new value.
>       public func withVar<T>(_ item: T, update: @noescape (inout T) throws -> 
> Void) rethrows -> T {
>         var this = item
>         try update(&this)
>         return this
>       }
> 
> -- 
> 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

Reply via email to