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.