Imagine a situation that John have two childrens Alice and Bob, and Bob have a cat Orion.
var Immutable = require('immutable'); var parent = Immutable.Map({name: 'John'}); var childrens = Immutable.List([ Immutable.Map({name: 'Alice', parent: parent}), Immutable.Map({name: 'Bob', parent: parent}) ]); var cat = Immutable.Map({name: 'Orion', owner: childrens.get(1)});
After few years John wants to rename to Jane.
var renamedParent = parent.set('name', 'Jane');
...and let childrens know about it.
childrens = childrens.map(function(children) { children.set('parent', renamedParent); });
Then I have to update cat because Bob changed.
cat = cat.set('owner', childrens.get(1));
Is it possible to automatically update all related objects when one object change? I looked at Cursors, but I'm not sure if they are a solution. If it possible, can you give me an example?
Immutables are the objects whose state cannot be changed once the object is created. Strings and Numbers are Immutable.
The object being frozen is said to be immutable because the entire object state (values and references to other objects) within the whole object is fixed. Note that strings, numbers, and booleans are always immutable and that Functions and Arrays are objects.
Using ImmutableJS can improve dramatically the performance of your application. And, because the immutable data never changes, you can always expect new data to be passed from the above. To make sure you are correctly comparing the data and not updating the UI when there is no change, you should always use the .
String specifications among programming languages vary, however most languages treat them as reference types. But strings in JavaScript are different. They are immutable primitives. This means that the characters within them may not be changed and that any operations on strings actually create new strings.
Is it possible to automatically update all related objects when one object changes in an immutable collection?
No.
No, but nothing ever changes in an immutable data structure so that's not a problem.
It's more complicated...
The whole point of immutable objects is that if you have a reference to an immutable object you don't ever have to bother checking whether any of its properties have changed. So, is it a non-issue? Well...
There are some consequences of that - whether they are good or bad depends on your expectations:
Of course in practice we often deal with values that change in time. It may seem that immutable state can't describe mutable world but there are some ways people deal with it.
Look at it this way: if you have your address on some ID and you move to a different address, that ID should be changed to be consistent with new true data, because it is no longer true that you live at that address. But when you get an invoice when you buy something which contains your address and then you change your address, the invoice stays the same because it is still true that you lived at that address when the invoice was written. Some data representations in the real world are immutable, like invoices in that example, and some are mutable like IDs.
Now taking your example, if you choose to use immutable structures to model your data, you have to think about it in a way that you think about the invoice from my example. It may be true that the data is not up to date but it will always be consistent and true for some point in time, and it will never change.
So how to model change with immutable data? There is a nice way it has been solved in Clojure using Vars, Refs, Atoms, and Agents, and ClojureScript (a compiler for Clojure that targets JavaScript) supports some of them (in particular Atoms are supposed to work as in Clojure but there are no Refs, STM, Vars or Agents - see what are the differences between ClojureScript and Clojure regarding concurrency features).
Looking at how Atoms are implemented in ClojureScript it seems that you can just use ordinary JavaScript objects to achieve the same. It will work for things like having a JavaScript object that is itself mutable, but it has a property that is a reference to an immutable object - you will not be able to change any properties of that immutable object, but you will be able to construct a different immutable object, and swap the old one to the new one in your top-level mutable object.
Other languages like Haskell that are purely functional may have different ways to deal with mutable world, like monads (a concept notoriously hard to explain - Douglas Crockford, author of JavaScript: The Good Parts and discoverer of JSON attributes it to "the monadic curse" in his talk Monads and Gonads).
Your question seems simple but the problem it touches is actually quite complicated. Of course it would be missing the point to just answer "No" to your question whether it is possible to automatically update all related objects when one object changes, but it is more complicated than that, and saying that in immutable objects nothing ever changes (so this problem never happens) will be equally unhelpful.
You can have a top level object or variable from which you always access all your structures. Let's say you have:
var data = { value: Immutable.Map({...}) }
If you always access your data using data.value
(or with some better names) then you can pass the data
to some other part of your code, and whenever your state changes you can just assign a new Immutable.Map({...}) to your data.value
and at that point all your code that uses data
will get fresh values.
How and when to update the data.value
to a new immutable structure could be solved by making it automatically triggered from your setter functions that you would use to update your state.
Another way would be to use similar tricks at the level of every structure, for example - I use the original spelling of the variables:
var parent = {data: Immutable.Map({name: 'John'}) }; var childrens = {data: Immutable.List([ Immutable.Map({name: 'Alice', parent: parent}), Immutable.Map({name: 'Bob', parent: parent}) ])};
but then you have to remember that what you have as values are not immutable structures but rather those additional objects with references to immutable structures that introduce an additional level of indirection.
What I would suggest is to look at some of those projects and articles:
I hope this answer even if not giving a simple solution will nevertheless be helpful, because describing mutable world with immutable structures is a very interesting and important problem.
For a different approach to immutability, with immutable objects that are proxies to data that is not necessarily constant, see the Immutable Objects vs. Common Sense webinar by Yegor Bugayenko and his articles:
Yegor Bugayenko uses the term "immutable" in a slightly different sense than what it usually means in the context of functional programming. Instead of using immutable or persistent data structures and functional programming, he advocates the use of object oriented programming in the original sense of the term in a way that you never actually mutate any object but you can ask it to change some state, or mutate some data, that is itself considered to be separate from the object. It's easy to imagine an immutable object that talks to a relational database. The object itself can be immutable but it can still update the data stored in the database. It's somewhat harder to imagine that some data stored in RAM can be thought of as equally separate from the object as the data in the database but there is really not much difference. If you think about objects as autonomous entities that expose some behavior and you respect their abstraction boundaries then it actually makes a lot of sense to think about objects as something different than just data and then you can have immutable objects with mutable data.
Please comment if anything needs some clarification.
As rsp clarified, this problem reflects the inherent trade-off offered by immutability.
Here's an example react/flux-ish app demonstrating one way to deal with this problem. The key here is that numeric IDs are used for reference rather than Javascript references.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With