Open dferens opened 8 years ago
@dferens Consider this situation (a common pattern in Hoplon applications):
(defc= org ...) ;; some formula cell
(defn login!
"Maybe does AJAX request, or something..."
[user pass org]
...)
;; The DOM:
(html
(head)
(body
(let [user (cell nil)
pass (cell nil)]
(form
:submit #(login! @user @pass @org)
(label "User:" (input :keyup #(reset! user @%))) (br)
(label "Pass:" (input :type "password" :keyup #(reset! pass @%)))))))
Notice how the org
formula cell is dereferenced asynchronously, so there are no "listeners" on it. How would something like that work?
I'm sorry if I don't understand implementation of javelin properly.
If org
cell has no listeners on it, why can't we compute formula once on deref stage instead of computing it multiple times when some source cell updates?
We could, but i believe the bookkeeping involved would actually make things slower.
Also currently cells can contain state and perform side effects, like this, for instance:
(let [i-saw-a-dog (atom false)]
(defc= c
(do (when (= othercell "dog") (reset! i-saw-a-dog true))
(str "hello, " othercell " i saw a dog is " @i-saw-a-dog))))
Lazy evaluation would make this kind of stateful cell impossible, because you might attach a listener or dereference after othercell
has had the value of "dog"
once but no longer does at the moment.
Can't we introduce another type of formula cell which exposes this lazy behaviour? Like:
(defc~ i (+ a 1))
And it will propagate its value only when there are some other cells watching it, or when some code is deref
-ing it.
The goal of this stuff is to increase efficiency . If you have a lot of pure functions over some cell which simply transforms your data, you will compute just what you need.
Just want to share a note that MobX (https://mobxjs.github.io/mobx/refguide/api.html, what a similarity to Javelin!) separates pure computed values (ie. pure formula cell) vs. reactions (ie. side-effecting formula cells). Hence, the former can be evaluated lazily, and the later eagerly.
Here is a blog by MobX's creator that explains the rational and what/how it accomplishes.
Cheers!
i think this is relevant https://github.com/hoplon/javelin/issues/37
rather than introduce a new but still hard-coded propagation mechanism, i'd personally like to see custom/extensible propagations implemented first, then a discussion of what specific propagation strategies should ship with core.
also this is spot on in the linked article above:
Any imperative action that an application takes in response to a state change usually creates or updates some values. In other words, most actions manage a local cache. Triggering the user interface to update? Updating aggregated values? Notifying the back-end? These can all be thought of as cache invalidations in disguise. To ensure these caches will stay in sync, you need to subscribe to future state changes that will enable your actions to be triggered again.
we can go back and forward on implementation details but everything ultimately boils down to cache management, which AFAIK has no truly general "one size fits all" solution.
Hi,
So basically there is no need to propagate updates to cells which have no listeners.
Imagine you have this cell structure and you are building app which tracks some other cell i. So, when a updates there is no need to compute cells e, f, g and h and we can defer that computation to deref call.![javelin-1](https://cloud.githubusercontent.com/assets/1489339/15286290/d78e7774-1b64-11e6-8519-9fc801fa117e.png)
Does it make sense? Thanks.