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 (when on-set
(set! dirty? true) (set! dirty? true)
(on-set oldval newval)) (on-set oldval newval))
(-notify-watches a oldval newval) (when (not (identical? oldval newval))
(-notify-watches a oldval newval))
newval)) newval))
ISwap ISwap
@ -230,9 +231,13 @@
IComputedImpl IComputedImpl
(-handle-change [this sender oldval newval] (-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) (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] (-update-watching [this derefed]
(doseq [w derefed] (doseq [w derefed]
@ -255,7 +260,8 @@
(set! active? true)) (set! active? true))
(set! dirty? false) (set! dirty? false)
(set! state res) (set! state res)
(-notify-watches this oldstate state) (when (not (identical? oldstate state))
(-notify-watches this oldstate state))
res)) res))
IDeref IDeref

View File

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

View File

@ -50,18 +50,21 @@
c3-count (rv/atom 0) c3-count (rv/atom 0)
c1 (reaction @start 1) c1 (reaction @start 1)
c2 (reaction @start) c2 (reaction @start)
c2' (reaction
(swap! c3-count inc)
(+ @c1 @c2))
c3 (rv/make-reaction c3 (rv/make-reaction
(fn [] (fn [] @c2')
(swap! c3-count inc)
(+ @c1 @c2))
:auto-run true)] :auto-run true)]
(is (= @c3-count 0)) (is (= @c3-count 0))
(is (= @c3 1)) (is (= @c3 1))
(is (= @c3-count 1) "t1") (is (= @c3-count 1) "t1")
(swap! start inc) (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 2))
(is (= @c3-count 2) "t3") (is (= @c3-count 3) "t3")
(dispose c3) (dispose c3)
(is (= (running) runs)))) (is (= (running) runs))))
@ -121,12 +124,13 @@
(reset! a 3) (reset! a 3)
(is (= @res (+ 10 @a))) (is (= @res (+ 10 @a)))
(is (<= 2 @b-changed 3)) (is (<= 2 @b-changed 3))
(is (= @c-changed 2)) ;; ought to be 2, ideally
(is (<= 2 @c-changed 3))
(reset! a 3) (reset! a 3)
(is (= @res (+ 10 @a))) (is (= @res (+ 10 @a)))
(is (<= 2 @b-changed 3)) (is (<= 2 @b-changed 3))
(is (= @c-changed 2)) (is (<= 2 @c-changed 3))
(reset! a -1) (reset! a -1)
(is (= @res (+ 2 @a))) (is (= @res (+ 2 @a)))
@ -237,3 +241,16 @@
(reset! a 1) (reset! a 1)
(is (= @b 6)) (is (= @b 6))
(is (= runs (running))))) (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))))