Why would I want to have a thing in memory, copy it to more memory, modify the copy, then free up the original memory every time? That just seems like a waste.
> Why would I want to have a thing in memory, copy it to more memory, modify the copy, then free up the original memory every time?
You don't do that, runtime does that for you.
The main benefit is better assumptions about code you write. The prime example is how different languages handle object construction and modification:
var date = new Date(2022, 11, 21)
var other = date.addDays(10)
The question is: what do `date` and `other` contain?
Depending on the language the answer may surprise you. Some languages modify `date`. Others don't. And you never know which of the methods exposed on an object modify it unless you read documentation. Neither the compiler nor the type system can help you.
However, if objects are immutable, you are guaranteed that the original object, `date` is never modified. And if you need to use it again, you know it contains the same data without it suddenly changing.
This gives rise to another important property: you can send this to another thread without mutexes or without creating weird synchronization points like Java's AtomicInteger. Since the object cannot be mutated, threads don't have to fight for exclusive access to read it.
The reason I like it is that I have spent a lot of time debugging bar code like:
Var object=object()
If (isValid(object))
// Do something
In which the isValid function modified the object in unexpected way and caused the issue. With mutability, I loose confidence in the code and literally have to read implementation of everything the object touches to be sure i understand what's going on. Much more relevant in bigger projects.
Suppose you want to draw a six sided star. You could do it by drawing a triangle and then invert that triangle and draw it again. But suppose you want to cache the two triangles so that the next time you draw it will happen more quickly. You have some "Triangle invert(Triangle t)" function. It takes a triangle and returns the inverted version of that triangle. If that function modifies the triangle in place then you will first have to make a copy of it to make sure that you have the original triangle. If the code is written in a functional language you can assume that the funtion will always return a copy. If it is not functional then you may not know whether the function returns a copy or not and it may come as a "surprise" that the function modified the triangle in place.
In theory the functional approach is more stable and predictable. But whether this really causes a lot of bugs in practice is another question.
Why would I want to have a thing in memory, copy it to more memory, modify the copy, then free up the original memory every time? That just seems like a waste.