5 ms·
I don't get the point of "immutable objects". Why have an object at all? Why not just hardcode the values if you want them not to change?
by Gordonjcp 4y ago
I don't get the point of "immutable objects". Why have an object at all? Why not just hardcode the values if you want them not to change?
- i_no_can_eat 4y agoimmutable means that you set them only once, typically at runtime. Not that they have the same values always, everytime you run.
- deleted 4y ago[deleted]
- dopidopHN 4y agoThose are often records from a database. There is a way to change it, it’s to make a copy of it. I like being able to trust that something is what I think it is because it cannot be something else. Meaning: if I know that something can’t change, I don’t have to check for eventual accidental change.
- Gordonjcp 4y agoBut now you've got two versions of it that aren't the same. Why is that supposed to be good?
- naasking 4y agoBecause of aliasing. Some other functions/objects/threads may have a reference to the old version. If they were in the middle of a computation using that object, they don't have to add a whole bunch of checks to ensure that the data they're holding didn't suddenly change from underneath them. This happens a lot in concurrent programming, but even in single-threaded programs it makes reasoning about the current state of the system easier.
- Gordonjcp 4y agoSo you've just made the internal state of your program inconsistent? Why is this supposed to be good?
- naasking 4y agoNo, it's not inconsistent. If you want to call this inconsistent, then the mutable version of the program is also inconsistent.
- Gordonjcp 4y agoIt can't be inconsistent. You've got one copy of the data in memory, everything uses that, everything sees the same thing. What's the use case of all this copying and shunting stuff around and consuming massive amounts of memory? What kind of programs would you write that would benefit from this?
- dopidopHN 4y agoConcurrent programs where several threads read the same stream of data. For instance. But a more common case is how I get my records from my db. Only the ORM can create those DB record for me ( because I set it up that way ) When I return a response; I compose another immutable response object. And only my service layer can don that. ( it won’t compile elsewhere)
- naasking 4y ago> It can't be inconsistent. You've got one copy of the data in memory, everything uses that, everything sees the same thing. Wrong. For instance, state can be stored in locals. Two threads accessing the same structure, one reading and one writing, the reader loads some state into locals and the writer then invalidates that state in the middle of the reader's computation, and the reader proceeds to computing a result mixing old state and new state thus leading to inconsistency. This ABA problem is well known and it just can't happen if the structure is immutable. And this doesn't even go into cache coherency issues. I frankly don't think you appreciate the number of hazards just making data structures immutable actually addresses, and given you don't seem aware of the hazards implicit to mutable data structures, I suppose that's not surprising. > What kind of programs would you write that would benefit from this Pretty much every single program that accesses a relational database benefits from this. There are a few of those around n in case you didn't know. Perhaps you've heard of multiversion concurrency control?
- TeMPOraL 4y agoThe point is that if you have a reference to such object, you know for sure it'll stay looking the same way at all times, no matter what happens in the program. E.g. take this pseudocode: let foo = MakeMeAnObject(); let bar = MakeSomethingElse(foo); DoSomethingForSideEffects(foo, JoinThings(bar, baz)); return foo; With immutable objects, you can be certain that neither foo nor bar were modified by any of this code. So, when e.g. debugging a problem with that DoSomethingForSideEffects() call, you don't have to worry about values of foo and bar having been changed somewhere, by someone, between their introduction and the point you're debugging. Neither of them can be modified by it in the future - e.g. someone else can't change MakeSomethingElse() to also modify its inputs, thereby accidentally breaking your code that's using this function. Another way of looking at it: a lot of problems with reasoning about code, or parallelism, can be drastically simplified by assuming the data being passed around is only copied, and not modified in-place. "Immutable objects" as a language feature is just making this assumption the default, and enforcing it at the language/compiler level. In terms of use, it isn't that much more inconvenient over mutable objects. You can always do something like: foo = DoSomeTransformation(foo); 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. The obvious drawback here is, for large data structures, there will be lot of copying involved - but that's where the languages with immutable objects are usually "cheating", e.g. by using sophisticated data structures masquerading as simple ones, as to only ever copy things that have actually changed (i.e. "distinct" objects end up sharing a lot of their data under the hood).
- Gordonjcp 4y ago> 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?
- bongobingo1 4y agoNot 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.
- ankurdhama 4y agoIt makes code easy to understand as you can easily identify what is input and what is output and can easily figure out the flow of data i.e what is being computed based on what. Without immutable objects a function taking object can mutate those objects and now they are acting as input and output, which leads to complexity.
- andrekandre 4y ago"immutable" is kind of overloaded term, but what it means in this context is an object itself doesn't mutate when you want to change a value (basically value semantics[0] instead of reference semantics[1]) for example (pseudocode) var newUser = Person(name: "some guy", age: 0) // newUser is replaced with a new object that is // initialized with field.name and previous age (0) // the old object is discarded newUser.name = field.name // object is passed as copy-on-write, assuming a 1 sec delay // it will print the objects values at this point in time // (age: 0) even if altered later async(after:1) { print(newUser.age) } // prints 0 // age was changed to 32 a nanosecond later, // but now a new object again is initialized // instead of mutated newUser.age = 32 print(newUser.age) // prints 32 ---------- output: 32 0 [0] https://en.wikipedia.org/wiki/Value_semantics https://en.wikipedia.org/wiki/Value_semantics [1] https://stackoverflow.com/questions/27084007/what-is-value-and-reference-semantics-and-the-difference https://stackoverflow.com/questions/27084007/what-is-value-a...
- andrekandre 4y agois something i wrote ↑ here incorrect or off-topic? would appreciate a correction!
- idontpost 4y ago
- jimbokun 4y agoThe idea is that a given object never changes, but it's straightforward and efficient to create a new object from the original one with some of the values changed. This is "safer" for any code still operating on the original object, as it will not be changed unexpectedly.
- spc476 4y agoIt's about trusting a function call. Imagine the following C functions: extern result fubar(struct foo *); extern result snafu(struct foo const *); Just by looking at the function prototype, I know that calling snafu() won't change the struct foo I pass it. I don't know what fubar() will do to it. Maybe it won't change, maybe it will. I'd have to check the implementation of fubar() to find out.