How do persistent data structures help make Om faster

205 views Asked by At

Om, the clojurescript wrapper of React, is said to be very fast because it leverages immutability. I can't understand how persistent data structures can help here.

What I have understood is that application state is an atom. This state is passed to functions (om components) that return virtual DOM nodes, so that creating a "patch" of the differences between the current virtual DOM and its previous state is much better then operating directly on the actual DOM.

But where persistent data structures can help here?

(def app-state (atom {:foo {:counter 0}))
(om/root click-counter app-state {:target ...}) 

for example click-counter render a button that when clicked increments the counter. So The transition function looks like this:

(dom/button #js {:onClick #(om/transact! app [:foo :counter] inc)} 
            (str "clicked " (-> app :foo :counter) " times"))

I undestand this: when onClick is executed clojurescript creates a new map (very efficiently) like this:

{:foo {:counter 1}}

and app-state now points to the new map. At this point Om is aware that the state is changed because it's just a matter of one equality check.

The problem here is that Om should still calculate the difference between the whole old virtual DOM and the new one. It doesn't know that just the counter is changed.

Where is my mistake?

1

There are 1 answers

3
Arthur Ulfeldt On

When the app state is stored in a persistent tree structure like a map it's immediately obvious which parts of the state tree didn't change, and don't need updating. This is because any change to a child changes the parent. With mutable data structures changes to the children don't have to change the parents.

So if your state looked like this:

{:part1 [1 2 3 4]
 :part2 [:a :b]}

and you make a new state by adding something in part2:

{:part1 [1 2 3 4]
 :part2 [:a :b :c]}

then the comparison function can look and see that the value in :part1 of the old and new state is the exact same object and therefore cannot have any changes to any nested state because it's immutable.