Ultimately one of the major goals of immutability is isolation of side effects.
Ultimately one of the major goals of immutability is isolation of side effects.
Maybe I'm discarding this too readily, but I don't think this idea of "local mutability" has much value -- if an object is mutable, the compiler and runtime has to support mutation and many optimizations are impossible because every object is mutable somewhere during their lifetime (and for objects created in main, they're mutable for the lifetime of the program).
More, many modifications are flat out expected. You filled out a job application, you probably don't expect to change the job it is for. But you do expect that you can fill out your pieces, such that it is a modifiable document while you have it. (Back to the car example, it is expected that you used fuel and caused wear on the tires.)
As annoying as they were to deal with, the idea of having "frozen" objects actually fits really well with how many people want to think of things. You open it to get it ready for use. This will involve a fair bit of a setup. When done, you expect that you can freeze those and pass off to something else.
Transactions can also get into this. Not surprising, as they are part of the vocabulary we have built on how to deal with modifications. Same for synchronization and plenty of other terms. None of them go away if you just choose to use immutable objects.
In a language that isn't so precise, it's a lot harder to get value from the idea.
> Can the objects a function creates be mutated by functions they call?
No
> can functions modify their input parameters?
No
> If a function returns one of their input parameters (modified or not), does that mean the calling function can no longer mutate it?
No. Because the called function isn’t allowed to mutate its inputs, there’s no problem for the caller to mutate it. It’s irrelevant whether the input was also an output of the called function as it cannot mutate it anyway.
I suppose you can get into race conditions between caller and callee if your language provides asynchronicity and no further immutability guarantees. Still, you eliminated a whole lot of potential bugs