I\'ve read a couple of articles on immutability but still don\'t follow the concept very well.
I made a thread on here recently which mentioned immutability, but as
You cannot change an immutable object, therefore you must replace it.... "to change it". i.e. replace then discard. "Replacing" in this sense means changing the pointer from one memory location (of the old value) to another (for the new value).
Note that in doing so we now using additional memory. Some for the old value, some for the new value. Also note, some people get confused because they look at code, such as:
string mystring = "inital value";
mystring = "new value";
System.Console.WriteLine(mystring); // Outputs "new value";
and think to themselves, "but I am changing it, look right there, in black and white! mystring outputs 'new value'...... I thought you said i couldn't change it?!!"
But actually under the hood, whats happening is this allocation of new memory i.e. mystring is now pointing at a different memory address and space. "Immutable" in this sense, is not referring to the value of mystring but rather the memory used by the variable mystring to store its value.
In certain languages the memory storing the old value must be manually cleaned up i.e. the programmer must explicitly release it..... and remember to do so. In other languages this is an automatic feature of the language i.e. garbage collection in .Net.
One of the places this really blows out re:memory usage is in highly iterative loops, specially with strings as in Ashs' post. Say you were building an HTML page in an iterative loop, where you constantly appended the next HTML block to the last and, just for kicks, you were doing this on a high volume server. This constant allocation of "new value memory" can quickly get expensive, and ultimately fatal, if the "old value memory", is not properly cleaned up.
Another problem is that some people assume things like garbage collection (GC) happens immediately. But it doesn't. There are various optimizations that occur such that garbage collection is set to occur during the more idle periods. So there can be a significant delay between when the memory is marked as discarded and when it is actually freed by the garbage collector.... so you can suffer large memory usage spikes if you simply defer the problem to the GC.
If the GC doesn't get a chance to operate before you run out of memory, then things wont necessarily fall over like in other languages that don't have automatic garbage collection. Instead the GC will kick in as the highest priority process to free up the discarded memory, no matter how bad the timing, and become a blocking process while it cleans things up. Obviously, this isn't cool.
So basically, you need to code with these things in mind and look into the documentation for the languages you are using for the best practices/patterns that allow you to avoid/mitigate this risk.
As in Ashs' post, in .Net and with strings, the recommended practice is to use the mutable StringBuilder class, rather than the immutable string classes when it comes to the need to constantly change a strings value.
Other languages/types will similarly have their own workarounds.