More advanced mirroring is one of those things that is on the agenda somewhere. It would stand to reason that a generalizable solution which doesn't need to be created for each struct would become possible when that arrives, no?
On Mon, Dec 19, 2016 at 16:08 Andy Chou via swift-evolution < [email protected]> wrote: > Value semantics help reduce the issues around mutability, but they don't > go away completely. I would like to create structs that are completely > immutable after construction. Turning the properties into vars > unfortunately loses this idea. > > The proposed 'with' function doesn't construct new instances, which means > the let constants are already set. Nick's solution works, as it's basically > a copy constructor that allows for changes while the new object is > constructed. But it needs to be created for each struct. Which I'm fine > with :) > > Andy > > On Dec 19, 2016, at 1:47 PM, Derrick Ho <[email protected]> wrote: > > That is correct Andy. Let-constant can not be assigned a new value after > it gets its initial value. > > It is unclear why you are against turning your properties into var's. > Because you are using structs, all properties are copied by value. > > struct Person { > var name: String > } > > let andy = Person(name: "Andy") > var brandon = andy; brandon.name = "Brandon" > > andy.name // "Andy" > brandon.name // "Brandon" > > I believe this accomplishes the same thing you wanted in with(name:) > > On Mon, Dec 19, 2016 at 1:26 PM Andy Chou via swift-evolution < > [email protected]> wrote: > > 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 > > Be aware that there's a bug that's being worked on: > > https://bugs.swift.org/browse/SR-2773 > > -- E > > > On Dec 19, 2016, at 12:40 PM, Andy Chou via swift-evolution < > [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]> 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]>, 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] > > > https://lists.swift.org/mailman/listinfo/swift-evolution > > > > > > > > > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution > > > > _______________________________________________ > > > swift-evolution mailing list > > > [email protected] > > > https://lists.swift.org/mailman/listinfo/swift-evolution > > > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
