Skip to content

Commit 35a3609

Browse files
anmonteiroswannodette
authored andcommitted
CLJS-2349: Port reset-vals! and swap-vals! over from Clojure
1 parent 998933f commit 35a3609

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

src/main/cljs/cljs/core.cljs

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4423,27 +4423,57 @@ reduces them without incurring seq initialization"
44234423
new-value))
44244424
(-reset! a new-value)))
44254425

4426+
(defn reset-vals!
4427+
"Sets the value of atom to newval. Returns [old new], the value of the
4428+
atom before and after the reset."
4429+
{:added "1.9"}
4430+
[a new-value]
4431+
(let [validate (.-validator a)]
4432+
(when-not (nil? validate)
4433+
(when-not (validate new-value)
4434+
(throw (js/Error. "Validator rejected reference state"))))
4435+
(let [old-value (.-state a)]
4436+
(set! (.-state a) new-value)
4437+
(when-not (nil? (.-watches a))
4438+
(-notify-watches a old-value new-value))
4439+
[old-value new-value])))
4440+
44264441
(defn swap!
44274442
"Atomically swaps the value of atom to be:
44284443
(apply f current-value-of-atom args). Note that f may be called
44294444
multiple times, and thus should be free of side effects. Returns
44304445
the value that was swapped in."
44314446
([a f]
4432-
(if (instance? Atom a)
4433-
(reset! a (f (.-state a)))
4434-
(-swap! a f)))
4447+
(if (instance? Atom a)
4448+
(reset! a (f (.-state a)))
4449+
(-swap! a f)))
4450+
([a f x]
4451+
(if (instance? Atom a)
4452+
(reset! a (f (.-state a) x))
4453+
(-swap! a f x)))
4454+
([a f x y]
4455+
(if (instance? Atom a)
4456+
(reset! a (f (.-state a) x y))
4457+
(-swap! a f x y)))
4458+
([a f x y & more]
4459+
(if (instance? Atom a)
4460+
(reset! a (apply f (.-state a) x y more))
4461+
(-swap! a f x y more))))
4462+
4463+
(defn swap-vals!
4464+
"Atomically swaps the value of atom to be:
4465+
(apply f current-value-of-atom args). Note that f may be called
4466+
multiple times, and thus should be free of side effects.
4467+
Returns [old new], the value of the atom before and after the swap."
4468+
{:added "1.9"}
4469+
([a f]
4470+
(reset-vals! a (f (.-state a))))
44354471
([a f x]
4436-
(if (instance? Atom a)
4437-
(reset! a (f (.-state a) x))
4438-
(-swap! a f x)))
4472+
(reset-vals! a (f (.-state a) x)))
44394473
([a f x y]
4440-
(if (instance? Atom a)
4441-
(reset! a (f (.-state a) x y))
4442-
(-swap! a f x y)))
4474+
(reset-vals! a (f (.-state a) x y)))
44434475
([a f x y & more]
4444-
(if (instance? Atom a)
4445-
(reset! a (apply f (.-state a) x y more))
4446-
(-swap! a f x y more))))
4476+
(reset-vals! a (apply f (.-state a) x y more))))
44474477

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

src/test/cljs/cljs/core_test.cljs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,31 @@
14481448
(is (= "#js {:_abc 1}" (pr-str #js {"_abc" 1})))
14491449
(is (= "#js {:*compiler* 1}" (pr-str #js {"*compiler*" 1}))))
14501450

1451+
(deftest swap-vals-returns-old-value
1452+
(let [a (atom 0)]
1453+
(is (= [0 1] (swap-vals! a inc)))
1454+
(is (= [1 2] (swap-vals! a inc)))
1455+
(is (= 2 @a))))
1456+
1457+
(deftest deref-swap-arities
1458+
(binding [*warn-on-reflection* true]
1459+
(let [a (atom 0)]
1460+
(is (= [0 1] (swap-vals! a + 1)))
1461+
(is (= [1 3] (swap-vals! a + 1 1)))
1462+
(is (= [3 6] (swap-vals! a + 1 1 1)))
1463+
(is (= [6 10] (swap-vals! a + 1 1 1 1)))
1464+
(is (= 10 @a)))))
1465+
1466+
(deftest deref-reset-returns-old-value
1467+
(let [a (atom 0)]
1468+
(is (= [0 :b] (reset-vals! a :b)))
1469+
(is (= [:b 45M] (reset-vals! a 45M)))
1470+
(is (= 45M @a))))
1471+
1472+
(deftest reset-on-deref-reset-equality
1473+
(let [a (atom :usual-value)]
1474+
(is (= :usual-value (reset! a (first (reset-vals! a :almost-never-seen-value)))))))
1475+
14511476
(comment
14521477
;; ObjMap
14531478
;; (let [ks (map (partial str "foo") (range 500))

0 commit comments

Comments
 (0)