My guess is that Clojure's fmap behaves that way because it is modeled
after Haskell's fmap, which only accepts functions that operate only
on the values due to the way fmap (and the Functor typeclass that fmap
belongs to) is modeled in Haskell's type system.

To pass both keys and values to your transforming function, I think
Alan's idea of using 'walk' is the best:

(use '[clojure.walk :only (walk)])

(def my-map  {:first "john" :last "smith" :age 25})

(defn my-fn [[key value]]
  (if (string? value)
    [key (.toUpperCase value)]
    [key value]))

user=> (walk my-fn identity my-map)
{:first "JOHN", :last "SMITH", :age 25}

On Feb 23, 6:27 am, Chris Maier <christopher.ma...@gmail.com> wrote:
> Can anybody explain why fmap, when operating on an IPersistentMap,
> only passes the function the value of the map entry, instead of the
> entire map entry (i.e., the key and value pair)?  It seems a bit odd
> in that all the other implementations of fmap operate on the entire
> item in the sequence.  Also, I can imagine cases where you'd want to
> do some map transformation that also depends on the key (do something
> for entries A, B, and C, but something else for entries X, Y, and Z).
>
> I suppose I could use remove-method and then write my own fmap
> implementation for IPersistentMap.  I'm curious about the design,
> though.
>
> Thanks,
> Chris
>
>
>
>
>
>
>
> On Tue, Feb 22, 2011 at 6:56 PM, Benny Tsai <benny.t...@gmail.com> wrote:
> > There is fmap from clojure.contrib.generic.functor, which expects a
> > function of arity 1, for just the value:
>
> > (use 'clojure.contrib.generic.functor)
> > (require '[clojure.string :as str])
>
> > (def my-map {:first "john" :last "smith" :age 25})
>
> > (defn my-fn [value]
> >  (if (string? value)
> >    (str/upper-case value)
> >    value))
>
> > user=> (fmap my-fn my-map)
> > {:first "JOHN", :last "SMITH", :age 25}
>
> > On Feb 22, 4:23 pm, rob levy <r.p.l...@gmail.com> wrote:
> >> The usual intuitive options for this are reduce, zipmap, or into.  You can
> >> also write a lazily recursive solution.  I wonder why there's no function 
> >> in
> >> core that lazily re-constructs the map with the results of the function?  
> >> It
> >> seems to have been discussed on the list at least once or twice.  It seems
> >> like there would have to be two versions of it, one expecting a function
> >> with an arity of one (for just the value) and another expecting an arity of
> >> two (key and value).
>
> >> On Mon, Feb 21, 2011 at 10:08 PM, yair <yair....@gmail.com> wrote:
> >> > I'm hoping this is a dumb question and I've missed something obvious.
> >> > I have a map with various key-value pairs and I want to transform some
> >> > of the values, e.g.
>
> >> > (def mymap {:first "john" :last "smith" :age 25}) and say I want to
> >> > change the strings to be upper case.
> >> > Right now all I can think of doing is using reduce and passing in an
> >> > empty map and the re-associating each key with the (possibly)
> >> > transformed value.  Is there something like the map function that
> >> > takes two parameters, one a function that receives a pair and returns
> >> > a new pair, and the other a map, and returns a map that's
> >> > reconstituted from those pairs?
>
> >> > Thanks
>
> >> > --
> >> > 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