On Tue, Oct 09, 2012 at 15:31 -0700, Jean Niklas L'orange wrote:
>    On Tuesday, October 9, 2012 9:14:51 PM UTC+2, Wolodja Wentland wrote:
> 
>      --- snip ---
>      (reduce-kv
>       (fn [ret k v]
>        (assoc ret k (func-that-does-something-with v)))
>       some-map))
>      --- snip --
> 
>      I am using reducers in other places, but am not entirely sure how to
>      employ
>      them here. I would be grateful for any advice.
> 
>    You could use merge as the combine function, and let (fn [ret [k
>    v]] (assoc ret k (func-that-does-something-with v))) be the reducing
>    function you pass to fold. Then it's at least parallelisable, though I'm
>    unsure of its performance.

I played with the following implementation:

    (defn update-vals
      [m f]
      (persistent!
        (reduce-kv
          (fn [ret k v]
            (assoc! ret k (f v)))
          (transient {})
          m)))

    (defn pupdate-vals
      [m f]
      (r/fold
        (r/monoid merge hash-map)
        (fn [ret [k v]]
          (conj ret [k (f v)]))
        (vec m)))

    (defn foo
      [x]
      (Thread/sleep 0.2)
      (inc x))

but unfortunately update-vals still outperforms pupdate-vals even on large
maps. I am not sure what else I can do to speed up folding into maps
(as opposed to a single value), but I'll keep on experimenting.

    user=> (def m (zipmap (range 100000) (range 100000)))
    #'user/m
    user=> (time (dotimes [_ 100] (pupdate-vals m inc)))
    "Elapsed time: 8068.950282 msecs"
    nil
    user=> (time (dotimes [_ 100] (update-vals m inc)))
    "Elapsed time: 1106.253256 msecs"
    nil
    user=> (time (dotimes [_ 100] (pupdate-vals m foo)))
    "Elapsed time: 8890.445481 msecs"
    nil
    user=> (time (dotimes [_ 100] (update-vals m foo)))
    "Elapsed time: 3954.917294 msecs"
-- 
Wolodja <[email protected]>

4096R/CAF14EFC
081C B7CD FF04 2BA9 94EA  36B2 8B7F 7D30 CAF1 4EFC

Attachment: signature.asc
Description: Digital signature

Reply via email to