Thanks Erica, I wasn't aware of that Swift evolution proposal. If I'm reading 
it right, this wouldn't work with structs with let-variables...?  Here's what I 
get with this example:

struct Person {
    let name: String
    let address: String
}

@discardableResult
public func with<T>(_ item: T, update: (inout T) throws -> Void) rethrows -> T {
    var this = item
    try update(&this)
    return this
}

let john = Person(name: "John", address: "1 battery st")
let jane: Person = with(john) { $0.name = "Jane" }     // Test.swift:24:41: 
Cannot assign to property: 'name' is a 'let' constant

Andy

> On Dec 19, 2016, at 11:44 AM, Erica Sadun <[email protected]> wrote:
> 
> https://github.com/apple/swift-evolution/pull/346 
> <https://github.com/apple/swift-evolution/pull/346>
> 
> Be aware that there's a bug that's being worked on:
> 
> https://bugs.swift.org/browse/SR-2773 <https://bugs.swift.org/browse/SR-2773>
> 
> -- E
> 
> 
>> On Dec 19, 2016, at 12:40 PM, Andy Chou via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> Of course. Thanks for pointing out the obvious solution. This preserves the 
>> immutability of the struct and doesn't require O(n^2) code for structs with 
>> large numbers of fields. 
>> 
>> I was thinking of a generic solution - perhaps something like a synthetic 
>> initializer that does what your solution does. But that may be overkill 
>> given how relatively easy it is to do this per struct...
>> 
>> On the other hand a generic solution would encourage using immutable 
>> structs. I wasted too much time trying to solve this, I suspect others would 
>> just give up and use var, or even classes. 
>> 
>> Andy
>> 
>> On Dec 19, 2016, at 10:43 AM, Nick Keets <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>> You are probably asking for a generic solution, but for a specific struct 
>>> you can implement it like this:
>>> 
>>> extension Person {
>>>     func with(name: String? = nil, address: String? = nil, phone: String? = 
>>> nil) -> Person {
>>>         let name = name ?? self.name
>>>         let address = address ?? self.address
>>>         let phone = phone ?? self.phone
>>>         return Person(name: name, address: address, phone: phone)
>>>     }
>>> }
>>> 
>>> 
>>> On 19 Dec 2016, 20:28 +0200, Andy Chou via swift-evolution 
>>> <[email protected] <mailto:[email protected]>>, wrote:
>>>> I like that structs are value types in Swift, this encourages the use of 
>>>> immutable data. O'Caml has an operator "with" that allows for copying an 
>>>> existing struct with a change to one field. I looked at Lenses for this 
>>>> functionality and it seems like a lot to digest for something so simple. I 
>>>> also tried to implement this using a constructor, or a function, and it 
>>>> was not obvious how to do so without a lot of code duplication.
>>>> 
>>>> What's I'm looking for is something like this (not necessarily with this 
>>>> syntax):
>>>> 
>>>> struct Person {
>>>> let name: String
>>>> let address: String
>>>> let phone: String
>>>> }
>>>> 
>>>> func f() {
>>>> let andy = Person(name: "Andy", address: "1 Battery St., San Francisco, 
>>>> CA", phone: "1234567")
>>>> let chris = andy.with(name: "Chris")
>>>> let dave = andy.with(address: "50 Townsend St., San Francisco, CA")
>>>> }
>>>> 
>>>> I tried to implement a "with" function like this but default arguments 
>>>> cannot reference properties of self. Same problem trying to do this in a 
>>>> constructor.
>>>> 
>>>> Obviously it's possible to create an entirely new Person specifying the 
>>>> values from an existing Person, but this is very tedious with structures 
>>>> with many properties.
>>>> 
>>>> Anyone taken a look at this before? Any suggestions?
>>>> 
>>>> Andy
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to