benleggiero
07/27/2017, 10:09 AMlet constant cannot be mutated, and if its type was defined as a struct, its sub-values cannot be mutated either, even if those were declared as `var`s.
So in Swift:
struct Foo {
var bar: String
}
var foo1 = Foo(bar: "Mutable A")
let foo2 = Foo(bar: "Immutable A")
foo1.bar = "Mutable B" // OK; foo1's bar is now "Mutable B"
foo1 = foo2 // OK; values in foo2 are COPIED into foo1. foo1's bar is now "Immutable A"
foo1.bar = "Mutable C" // OK; foo1's bar is now "Mutable C"
print(foo2.bar) // "Immutable"
foo2 = foo1 // COMPILE ERROR: cannot assign to value: 'foo2' is a 'let' constant
foo2.bar = "Immutable B" // COMPILE ERROR: cannot assign to property: 'foo2' is a 'let' constant
struct Baz {
var foo: Foo {
didSet {
print("foo changed from \(oldValue) to \(foo)")
}
}
}
var baz1 = Baz(foo: foo1) // New Baz with a COPY of foo1
let baz2 = Baz(foo: foo2) // New Baz with a COPY of foo2
baz1.foo.bar = "Mutable D" // OK; baz1's foo's bar is now "Mutable D". Prints the following: foo changed from Foo(bar: "Mutable C") to Foo(bar: "Mutable D")
print(foo1.bar) // "Mutable C"
baz1.foo = foo2 // OK; baz1's foo is now a COPY of foo2. Prints the following: foo changed from Foo(bar: "Mutable D") to Foo(bar: "Immutable A")
baz2 = baz1 // COMPILE ERROR: cannot assign to value: 'baz2' is a 'let' constant
baz2.foo.bar = "Immutable C" // COMPILE ERROR: cannot assign to property: 'baz2' is a 'let' constant
This is really great for piece-of-mind; if I write as much as possible in `struct`s, I know that let constants will always be the same value they started with. This is really great for hashing and passing values. As I also demonstrated, it allows for deeper knowledge of change; when I changed baz1.foo.bar, baz1 knew about that change and was able to take action, even though it doesn't own bar.
This would be really great in Kotlin! I'm not sure if it'd even be possible on the JVM to do the really deep linking, but at least the compile-time assurance that a `val`'s inner `var`s won't change.