On Sun, Aug 30, 2009 at 4:14 PM, kyle smith <[email protected]> wrote:

>
> I wrote this based on assoc-in.  If anyone thinks this should be in
> core or contrib, feel free to use it.
>
> (defn assoc-in-by
>  "'Updates' a value in a nested associative structure, where ks is a
>  sequence of keys and (f v) is the new value and returns a new nested
> structure.
>  If any levels do not exist, hash-maps will be created."
>  [m [k & ks] f]
>  (if ks
>    (assoc m k (assoc-in-by (get m k) ks f))
>    (assoc m k (f (get m k)))))


Nifty and seems to work. Here's a little demo:
user=> (assoc-in-by nil [:a :b :c] #(if (nil? %) 1 (inc %)))
{:a {:b {:c 1}}}
user=> (assoc-in-by *1 [:a :b :c] #(if (nil? %) 1 (inc %)))
{:a {:b {:c 2}}}
user=> (assoc-in-by *1 [:a :b :c] #(if (nil? %) 1 (inc %)))
{:a {:b {:c 3}}}
user=> (assoc-in-by *1 [:a :b :c] #(if (nil? %) 1 (inc %)))
{:a {:b {:c 4}}}
which has a counter incrementing.

And it's swap! and alter!-compatible:

(swap! foo assoc-in-by [:a :b :c] #(bar % baz))

Maybe a version that takes more args?

(defn assoc-in-by
 "'Updates' a value in a nested associative structure, where ks is a
 sequence of keys and (f v) is the new value and returns a new nested
structure.
 If any levels do not exist, hash-maps will be created."
 ([m [k & ks] f]
   (if ks
     (assoc m k (assoc-in-by (get m k) ks f))
     (assoc m k (f (get m k)))))
 ([m [k & ks] f args]
   (if ks
     (assoc m k (assoc-in-by (get m k) ks f args))
     (assoc m k (apply f (get m k) args)))))

which simplifies the swap! example to:

(swap! foo assoc-in-by [:a :b :c] bar baz)

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to