Sent from my iPad

> On Dec 20, 2016, at 4:32 AM, Jeremy Pereira via swift-evolution 
> <[email protected]> wrote:
> 
> 
>> On 20 Dec 2016, at 07:54, Pierre Monod-Broca via swift-evolution 
>> <[email protected]> wrote:
>> 
>> But for a struct to be immutable, you don't need all its properties to be 
>> let. (I guess that's Derrick's point)
> 
> Yes you do. Consider
> 
> struct Person: Hashable
> {
>    let firstName: String
>    let lastName: String
>    let hashValue: Int
> 
>    init(firstName: String, lastName: String)
>    {
>        self.firstName = firstName
>        self.lastName = lastName
>        self.hashValue = firstName.hashValue ^ lastName.hashValue
>    }
> }
> 
> func == (l: Person, r: Person) -> Bool
> {
>    return l.firstName == r.firstName && l.lastName == r.lastName
> }
> 
> Pretend that the hash value is quite expensive to calculate so I only want to 
> do it once. With the above code, this is fine but if I change the lets to 
> vars (e.g. var firstName: String), I am open to
> 
> let chris = Person(firstName: “Chris”, lastName: “Lattner”) // Immutable
> 
> var andy = chris
> andy.firstName = “Andy”
> 
> andy.hashValue // Gives the wrong answer unless you are exceptionally lucky.
> 
> I’ve used hashValue, but the same argument would apply to any computed 
> property where you might want to cache the computed value. As soon as you 
> make any of the properties that the computed property depends on `var`, you 
> have to add code that invalidates the cached value which is a performance and 
> a complexity hit for your struct.

The performance hit is likely a bit larger if you *don't* use a mutable 
property and instead create a whole new instance.

You are right that the need to recompute derived data adds complexity.  
'didSet' helps with that, but is still nontrivial if you were to have several 
derived values that depend on several properties each.  

It might be interesting to think about language solutions to reduce this 
complexity.   But in general, the mutability model of Swift's value types is an 
asset and should be embraced, not avoided.  That's what a "Swifty" solution 
would do IMO.

> 
> 
> 
>> 
>> ´´´
>> struct Person { /* . . . var properties . . . */ }
>> let john = Person() // john is completely immutable
>> ´´´
>> 
>> If a struct has var properties, you can do a mutable copy, change it, assign 
>> it to a new let, and you take advantage of immutability again.
>> 
>> ´´´
>> let jim = { var copy = john
>> copy.firstname = "Jim"
>> return copy
>> }()
>> 
>> func with<T>(_ original: T, transform: (inout T) -> ()) -> T {
>> var copy = original
>> transform(&copy)
>> return copy
>> }
>> 
>> let jane = with(john) { $0.firstname = "Jane" }
>> // jane is also immutable
>> ´´´
>> (I didn't check this compiles)
>> 
>> Pierre
>> 
>>> Le 19 déc. 2016 à 23:08, Andy Chou via swift-evolution 
>>> <[email protected]> a écrit :
>>> 
>>> 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
>> _______________________________________________
>> 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

Reply via email to