piercebot
piercebot

Reputation: 1827

Clojure: Checking equality of values with the same key across two atoms (using add-watch)

Let's say I have an atom:

(def pets (atom { :cats {} :dogs {} }))

I want to watch this atom for changes, so I create a watcher:

(add-watch pets :pet-watcher
  (fn [r k os ns]
    (when (not= os ns
      (println (str "Pets updated: " ns) )))))

Now, if I update my pets atom, I get notified of changes:

(swap! pets assoc-in [:dogs] {:name "Sparky" :color "Brown"})

; Pets updated: {:cats {}, :dogs {:name "Sparky", :color "Brown"}}

But what if I only want to be notified if :cats changes? I get an error when I try to compare properties of deref'd atoms:

; THIS DOES NOT WORK
(add-watch pets :cat-watcher
  (fn [r k os ns]
    (when (not= (:cats @os) (:cats @ns)
      (println (str "Cats updated: " (:cats @ns)) )))))

(swap! pets assoc-in [:cats] {:name "Whiskers" :color "Orange"})

; Error: No protocol method IDeref.-deref defined for type cljs.core/PersistentArrayMap

There must certainly be an elegant way to compare values with the same key across two atoms. How would you update my :cat-watcher to notify me of changes to just :cats?

Upvotes: 2

Views: 194

Answers (1)

Joost Diepenmaat
Joost Diepenmaat

Reputation: 17771

There is only one atom in your example.

You don't need to dereference os and ns in a watching function since it gets the old and new values of the atom not the atom itself. Just remove the @ signs in your code.

Upvotes: 4

Related Questions