Skip to content

Commit 8036032

Browse files
swannodettetonsky
andauthoredNov 16, 2023
CLJS-3406 implement reset-vals! and swap-vals! through protocols (#216)
Co-authored-by: Nikita Prokopov <niki@tonsky.me>
1 parent 067eaef commit 8036032

File tree

2 files changed

+67
-13
lines changed

2 files changed

+67
-13
lines changed
 

‎src/main/cljs/cljs/core.cljs

+23-13
Original file line numberDiff line numberDiff line change
@@ -4569,15 +4569,17 @@ reduces them without incurring seq initialization"
45694569
atom before and after the reset."
45704570
{:added "1.9"}
45714571
[a new-value]
4572-
(let [validate (.-validator a)]
4573-
(when-not (nil? validate)
4574-
(when-not (validate new-value)
4575-
(throw (js/Error. "Validator rejected reference state"))))
4576-
(let [old-value (.-state a)]
4577-
(set! (.-state a) new-value)
4578-
(when-not (nil? (.-watches a))
4579-
(-notify-watches a old-value new-value))
4580-
[old-value new-value])))
4572+
(if (instance? Atom a)
4573+
(let [validate (.-validator a)]
4574+
(when-not (nil? validate)
4575+
(when-not (validate new-value)
4576+
(throw (js/Error. "Validator rejected reference state"))))
4577+
(let [old-value (.-state a)]
4578+
(set! (.-state a) new-value)
4579+
(when-not (nil? (.-watches a))
4580+
(-notify-watches a old-value new-value))
4581+
[old-value new-value]))
4582+
[(-deref a) (-reset! a new-value)]))
45814583

45824584
(defn swap!
45834585
"Atomically swaps the value of atom to be:
@@ -4608,13 +4610,21 @@ reduces them without incurring seq initialization"
46084610
Returns [old new], the value of the atom before and after the swap."
46094611
{:added "1.9"}
46104612
([a f]
4611-
(reset-vals! a (f (.-state a))))
4613+
(if (instance? Atom a)
4614+
(reset-vals! a (f (.-state a)))
4615+
[(-deref a) (-swap! a f)]))
46124616
([a f x]
4613-
(reset-vals! a (f (.-state a) x)))
4617+
(if (instance? Atom a)
4618+
(reset-vals! a (f (.-state a) x))
4619+
[(-deref a) (-swap! a f x)]))
46144620
([a f x y]
4615-
(reset-vals! a (f (.-state a) x y)))
4621+
(if (instance? Atom a)
4622+
(reset-vals! a (f (.-state a) x y))
4623+
[(-deref a) (-swap! a f x y)]))
46164624
([a f x y & more]
4617-
(reset-vals! a (apply f (.-state a) x y more))))
4625+
(if (instance? Atom a)
4626+
(reset-vals! a (apply f (.-state a) x y more))
4627+
[(-deref a) (-swap! a f x y more)])))
46184628

46194629
(defn compare-and-set!
46204630
"Atomically sets the value of atom to newval if and only if the

‎src/test/cljs/cljs/core_test.cljs

+44
Original file line numberDiff line numberDiff line change
@@ -1998,3 +1998,47 @@
19981998
(let [a #js {}]
19991999
(set! a -x false)
20002000
(is (false? (.-x a))))))
2001+
2002+
(deftest test-cljs-3406
2003+
(testing "ISwap/IReset protocols"
2004+
(let [a (atom {:x 0})
2005+
c (reify
2006+
IDeref
2007+
(-deref [_]
2008+
(:x @a))
2009+
2010+
ISwap
2011+
(-swap! [o f]
2012+
(:x (swap! a update :x f)))
2013+
(-swap! [o f x]
2014+
(:x (swap! a update :x f x)))
2015+
(-swap! [o f x y]
2016+
(:x (swap! a update :x f x y)))
2017+
(-swap! [o f x y zs]
2018+
(:x (swap! a #(apply update % :x f x y zs))))
2019+
2020+
IReset
2021+
(-reset! [o new-value]
2022+
(:x (swap! a assoc :x new-value))))]
2023+
(is (= 0 @c))
2024+
(is (= 1 (swap! c inc)))
2025+
(is (= 1 @c))
2026+
(is (= 2 (swap! c + 1)))
2027+
(is (= 2 @c))
2028+
(is (= 5 (swap! c + 1 2)))
2029+
(is (= 5 @c))
2030+
(is (= 11 (swap! c + 1 2 3)))
2031+
(is (= 11 @c))
2032+
(is (= 0 (reset! c 0)))
2033+
(is (= 0 @c))
2034+
2035+
(is (= [0 1] (swap-vals! c inc)))
2036+
(is (= 1 @c))
2037+
(is (= [1 2] (swap-vals! c + 1)))
2038+
(is (= 2 @c))
2039+
(is (= [2 5] (swap-vals! c + 1 2)))
2040+
(is (= 5 @c))
2041+
(is (= [5 11] (swap-vals! c + 1 2 3)))
2042+
(is (= 11 @c))
2043+
(is (= [11 0] (reset-vals! c 0)))
2044+
(is (= 0 @c)))))

0 commit comments

Comments
 (0)
Please sign in to comment.