Here is one way to do it called update-in+.  It returns a vector consisting
of the new udpated value, like update-in does, followed by the original
value (in case you might want to see that for some reason), followed by the
updated value.

(defn update-in+
  ([m [k & ks] f & args]
     (if ks
       (let [[new-map old-val new-val] (apply update-in+ (get m k) ks f
args)]
         [(assoc m k new-map) old-val new-val])
       (let [old-val (get m k)
             new-val (apply f old-val args)]
         [(assoc m k new-val) old-val new-val]))))

Andy

On Thu, Apr 26, 2012 at 9:19 AM, Ambrose Bonnaire-Sergeant <
abonnaireserge...@gmail.com> wrote:

> Hi,
>
> You shouldn't need mutation for such a function.
>
> If you look at the source of update-in, it's fairly straightforward.
>
> (defn update-in
>   ([m [k & ks] f & args]
>    (if ks
>      (assoc m k (apply update-in (get m k) ks f args))
>      (assoc m k (apply f (get m k) args)))))
>
> Just create another function that returns a vector of the result of
> applying f, and the update-in result. It should be easy starting from
> update-in's source.
>
> (I'm not aware of an existing solution)
>
> Thanks,
> Ambrose
>
> On Fri, Apr 27, 2012 at 12:00 AM, blais <goo...@furius.ca> wrote:
>
>> Hi,
>> I have this use-case for (update-in) which keeps showing up in my code
>> which I don't have a solution for and I'm wondering if there isn't a
>> solution.
>> How do I _efficiently_ obtain the new value created by an invocation of
>> (update-in), that is, without having to get the modified value by lookups
>> in the new map?
>>
>> Simplified example:
>>
>> (def m {:planet {:country {:state {:city {:borough 4}}}}})
>>
>> (let [mm (update-in m
>>                     [:planet :country :state :city :borough]
>>                     (fn [old] (if (nil? old) 0 (inc old))))]
>>   (get-in mm [:planet :country :state :city :borough]))
>>
>> (update-in) returns the new/modified map, but what I want is to obtain
>> the new count returned by the anonymous function.
>> Having to call (get-in) right after is inefficient.
>>
>> This is obviously a contrived example for this question, but I have a lot
>> of real use cases for this (where at the top level of my app I have a ref
>> for a deep structure which changes as a response to network events).
>>
>> Is there an idiomatic way to do this without having to resort to
>> mutability?
>> (The only solution that comes to my mind is to wrap up update-in and the
>> modifier function with a special version that updates a local mutable and
>> return both the new map and the new object.)
>> Nasty?
>>
>> Thank you,
>>
>>
>>
>>  --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegroups.com
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+unsubscr...@googlegroups.com
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>
>
>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>

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

Reply via email to