Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> It's just that DoSomeTransformation() is not modifying the object, but instead returning a new instance of the same objects, with relevant fields having different values

I can't think of anything where I'd want that. Don't you end up needing infinite amounts of memory? Isn't it absolutely slow as balls copying all that stuff around?



Not really. You can copy the new parts and reference the old, garbage collect dead things, etc. At least in languages where immutability is a core tenet vs stuck on as an after thought.

Is it as fast mutable everything? No, some copy must happen, but is a mutable-standard languages as fast as raw hand tuned asm? Also (probably) no, but the trade offs are worth it. It likely matters a lot less than you think unless you're writing actually performance critical tight loop code vs just thinking about performance.


If immutability is a part of the language, then the compiler and the runtime know about it.

This way:

- passing an object around can always be by reference, since no one can change it

- depending on structures used, for changed bits you don't need to copy the entire structure, but simply shift pointers to old data or new data

- garbage collection can become trivial, and granular, since you know exactly what's new and old, and shifting data around becomes just moving pointers around (again, depends on implementation and optimisations)

There are downsides if you are not careful, of course:

- creating a bunch of new data that references old data will run out of memory, but this doesn't happen as often as you would think.

- sending data between processes/threads may result in copying that data (depends on implementation)

However, the upside is quite good: your data never changes under you. That is a call to func(data) doesn't sneakily change data. And all data becomes trivially thread-safe without mutexes or race conditions.


I guess I just don't get it.

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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: