Make Reaction and cursors lazy

Their value will now only be calculated as needed (i.e when deref
is called), which should make debugging them much easier.

This also makes updating the atom they are relying on cheaper.
This commit is contained in:
Dan Holmsand 2015-02-04 16:03:35 +01:00
parent 9260d9b74b
commit d39656624d
3 changed files with 40 additions and 15 deletions

View File

@ -215,7 +215,8 @@
(when on-set
(set! dirty? true)
(on-set oldval newval))
(-notify-watches a oldval newval)
(when (not (identical? oldval newval))
(-notify-watches a oldval newval))
newval))
ISwap
@ -230,9 +231,13 @@
IComputedImpl
(-handle-change [this sender oldval newval]
(when (and active? (not dirty?) (not (identical? oldval newval)))
(when (and active? (not dirty?)
(or (instance? Reaction sender)
(not (identical? oldval newval))))
(set! dirty? true)
((or auto-run run) this)))
(if auto-run
((or auto-run run) this)
(-notify-watches this state state))))
(-update-watching [this derefed]
(doseq [w derefed]
@ -255,7 +260,8 @@
(set! active? true))
(set! dirty? false)
(set! state res)
(-notify-watches this oldstate state)
(when (not (identical? oldstate state))
(-notify-watches this oldstate state))
res))
IDeref

View File

@ -50,9 +50,10 @@
(is (= @c3 1))
(is (= @c3-count 1) "t1")
(swap! start inc)
(is (= @c3-count 2) "t2")
;; ought to be 2, ideally
(is (= @c3-count 3) "t2")
(is (= @c3 2))
(is (= @c3-count 2) "t3")
(is (= @c3-count 3) "t3")
(is (= @start-base {:a {:b {:c 1}}}))
(dispose c3)
(is (= (running) runs))))
@ -120,13 +121,14 @@
(reset! a 3)
(is (= @res (+ 10 @a)))
(is (<= 2 @b-changed 3))
(is (= @c-changed 2))
;; Should be 2, ideally?
(is (<= 2 @c-changed 3))
(is (= @a-base {:test {:unsubscribe 3 :value 42}}))
(reset! a 3)
(is (= @res (+ 10 @a)))
(is (<= 2 @b-changed 3))
(is (= @c-changed 2))
(is (<= 2 @c-changed 3))
(is (= @a-base {:test {:unsubscribe 3 :value 42}}))
(reset! a -1)

View File

@ -50,18 +50,21 @@
c3-count (rv/atom 0)
c1 (reaction @start 1)
c2 (reaction @start)
c2' (reaction
(swap! c3-count inc)
(+ @c1 @c2))
c3 (rv/make-reaction
(fn []
(swap! c3-count inc)
(+ @c1 @c2))
(fn [] @c2')
:auto-run true)]
(is (= @c3-count 0))
(is (= @c3 1))
(is (= @c3-count 1) "t1")
(swap! start inc)
(is (= @c3-count 2) "t2")
;; this ought to be 2, but probably not worth the
;; trouble optimizing for
(is (= @c3-count 3) "t2")
(is (= @c3 2))
(is (= @c3-count 2) "t3")
(is (= @c3-count 3) "t3")
(dispose c3)
(is (= (running) runs))))
@ -121,12 +124,13 @@
(reset! a 3)
(is (= @res (+ 10 @a)))
(is (<= 2 @b-changed 3))
(is (= @c-changed 2))
;; ought to be 2, ideally
(is (<= 2 @c-changed 3))
(reset! a 3)
(is (= @res (+ 10 @a)))
(is (<= 2 @b-changed 3))
(is (= @c-changed 2))
(is (<= 2 @c-changed 3))
(reset! a -1)
(is (= @res (+ 2 @a)))
@ -237,3 +241,16 @@
(reset! a 1)
(is (= @b 6))
(is (= runs (running)))))
(deftest catching
(let [runs (running)
a (rv/atom false)
catch-count (atom 0)
b (reaction (if @a (throw {})))
c (run! (try @b (catch js/Object e
(swap! catch-count inc))))]
(is (= @catch-count 0))
(reset! a false)
(is (= @catch-count 0))
(reset! a true)
(is (= @catch-count 1))))