To var or let struct properties?

I don't understand what you're trying to achieve. Up-thread, it has already been stated by at least a few people, that maintaining invariants is one place where at least private(set) var should be used, if not let. The question was about rule-of-thumb, not about every conceivable case in existence.

At best, you are talking past each other, and at worst, you're being deliberately combative. I don't think there's any value in this discussion.

10 Likes

i was merely answering the original question and justifying my point that the rule of thumb is always let unless you absolutely need var. all imho.

As I mentioned above

If a struct has a memberwise initializer that doesn't do additional logic, all properties should be var, because an instance of it can always be rebuilt from any combination of values for the properties.

If it doesn't have it, like in your example, then let or private(set) var can be used to maintain invariants. Which invariants? Another litmus test is: does a property participate in the custom logic of a specialized initializer? If it doesn't, there's strong possibility that the property can be var, because the specialized initializer can simply be called again with all the same values but the one assigned to that property, and since the property doesn't matter in the internal logic of the initializer, its result will be exactly the same, with the only difference that that particular property will be different.

2 Likes

But maybe that's an effect you want. If a property provides an identity for instances of a type (for example the user id of a login account), forcing users of the type to create a new instance when they want to change that id makes the code reflect the semantics of the operation that has occurred i.e. you've got a struct that models a different account, not the same account but with the user id changed.

My rule of thumb is that things that need to vary are var and things that need to stay the same are let. The idea that it should usually be all or nothing per struct is absurd in my opinion. Do what's logical on a case by case basis.

2 Likes

A distinction between the two implies reference semantics; it would be unusual to model this with a struct. Indeed, though, if you are modeling a reference type with a struct, that would a reasonable corner case for which let properties may be important.

3 Likes

"vary" and "stay the same" are very, very different concepts when applied to types with value semantics, like structs, vs types with reference semantics, like classes.

For example, consider the struct

struct Person {
  let name: String
  var age: Int
}

the following code:

var p1 = Person(name: "Foo", age: 42)
// some more code...
p1.age += 1

has exactly the same meaning and produces the same effect as

var p1 = Person(name: "Foo", age: 42)
// some more code...
p1 = Person(name: p1.name, age: p1.age + 1)

but if Person was a class, the code would have a completely different meaning, and would produce a profoundly different effect.

2 Likes