Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update records in a ref map in Clojure?

Tags:

clojure

Given the following scenario:

(defrecord Person [firstname lastname])
(def some-map (ref {}))

(dosync
  (alter some-map conj {1 (Person. "john" "doe")})
  (alter some-map conj {2 (Person. "jane" "jameson")}))

To change the firstname of "joe" to "nick", I do the following:

(dosync
  (alter some-map (fn [m]                   
                  (assoc m 1 
                       (assoc (m 1) :firstname "nick")))))

What is the idiomatic way of doing this in Clojure?

like image 880
Odinodin Avatar asked Aug 17 '12 14:08

Odinodin


2 Answers

No need to use update-in, for this case, assoc-in is exactly what you want.

(dosync (alter some-map assoc-in [1 :firstname] "nick"))

like image 128
Joost Diepenmaat Avatar answered Oct 20 '22 16:10

Joost Diepenmaat


Edit: For your example assoc-in is better, since you ignore the previous value. Keeping this answer for cases where you actually need the previous value:

The update-in is there to update nested structures:

(alter some-map update-in [1 :firstname] (constantly "nick"))

The last argument is a function on the value to be "replaced" (like assoc, it does not replace but returns a new structure.) In this case the old value is ignored, hence the constantly function that always returns "nick".

like image 39
Rafał Dowgird Avatar answered Oct 20 '22 15:10

Rafał Dowgird