Re: Mapping a function over a map's values

2009-03-24 Thread Jon

Awesome.  Thanks Konrad.

On Mar 23, 4:11 am, Konrad Hinsen konrad.hin...@laposte.net wrote:
 On 22.03.2009, at 21:10, Jon Nadal wrote:



  I often need to map a function over the values of a map while
  preserving keys--something like:
 ...
  Is there a more concise way to do this in Clojure?  If not, is this
  something that might be worth putting in the contrib?

 Look at clojure.contrib.generic.functor/fmap. It does what you need  
 for maps, for all the other Clojure collections (where it works like  
 map except that its return value is a collection of the same type as  
 the input value), and you can implement it for any type you define  
 yourself, e.g. a tree structure.

 Konrad.
--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Jeff Valk

On Sun, 22 Mar 2009 at 23:27, Jeff Valk wrote:

 Ah, golf... :-)
 
 (defn mapmap [f m] 
   (into {} (for [[k v] m] [k (f v)])))

For the record, I think the original approach is the most clear. And it's 
actually shorter.

(defn mapmap [f m]
  (zipmap (keys m) (map f (vals m

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Konrad Hinsen

On 22.03.2009, at 21:10, Jon Nadal wrote:

 I often need to map a function over the values of a map while
 preserving keys--something like:
...
 Is there a more concise way to do this in Clojure?  If not, is this
 something that might be worth putting in the contrib?

Look at clojure.contrib.generic.functor/fmap. It does what you need  
for maps, for all the other Clojure collections (where it works like  
map except that its return value is a collection of the same type as  
the input value), and you can implement it for any type you define  
yourself, e.g. a tree structure.

Konrad.


--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Mark Engelberg

On Sun, Mar 22, 2009 at 11:53 PM, Jeff Valk jv-li...@tx.rr.com wrote:
 For the record, I think the original approach is the most clear. And it's 
 actually shorter.

 (defn mapmap [f m]
  (zipmap (keys m) (map f (vals m

But it traverses m twice, which is likely to be less efficient.

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Mark Volkmann

On Mon, Mar 23, 2009 at 3:11 AM, Konrad Hinsen
konrad.hin...@laposte.net wrote:

 On 22.03.2009, at 21:10, Jon Nadal wrote:

 I often need to map a function over the values of a map while
 preserving keys--something like:
 ...
 Is there a more concise way to do this in Clojure?  If not, is this
 something that might be worth putting in the contrib?

 Look at clojure.contrib.generic.functor/fmap. It does what you need
 for maps, for all the other Clojure collections (where it works like
 map except that its return value is a collection of the same type as
 the input value), and you can implement it for any type you define
 yourself, e.g. a tree structure.

This has methods for IPersistentVector, IPersistentSet, IPersistentMap
and ISeq. Why isn't there a method for IPersistentList?

-- 
R. Mark Volkmann
Object Computing, Inc.

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Konrad Hinsen

On Mar 23, 2009, at 12:15, Mark Volkmann wrote:

 Look at clojure.contrib.generic.functor/fmap. It does what you need
 for maps, for all the other Clojure collections (where it works like
 map except that its return value is a collection of the same type as
 the input value), and you can implement it for any type you define
 yourself, e.g. a tree structure.

 This has methods for IPersistentVector, IPersistentSet, IPersistentMap
 and ISeq. Why isn't there a method for IPersistentList?

Oversight. I'll add it!

That leaves the question whether there is still any need for the  
clojure.lang.ISeq implementation. At the moment it is used for lists,  
but that is not particularly consistent. I guess I will remove it.

Konrad.


--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Christophe Grand
I prefer the into version which allows to write a mapmap that preserves the
map type (eg sorted or hash):

(defn mapmap [f m]
  (into (empty m) (for [[k v] m] [k (f v)])))

Christophe
On Mon, Mar 23, 2009 at 7:53 AM, Jeff Valk jv-li...@tx.rr.com wrote:


 On Sun, 22 Mar 2009 at 23:27, Jeff Valk wrote:

  Ah, golf... :-)
 
  (defn mapmap [f m]
(into {} (for [[k v] m] [k (f v)])))

 For the record, I think the original approach is the most clear. And it's
 actually shorter.

 (defn mapmap [f m]
  (zipmap (keys m) (map f (vals m

 


--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Mark Volkmann

On Mon, Mar 23, 2009 at 7:04 AM, Konrad Hinsen
konrad.hin...@laposte.net wrote:

 On Mar 23, 2009, at 12:15, Mark Volkmann wrote:

 Look at clojure.contrib.generic.functor/fmap. It does what you need
 for maps, for all the other Clojure collections (where it works like
 map except that its return value is a collection of the same type as
 the input value), and you can implement it for any type you define
 yourself, e.g. a tree structure.

 This has methods for IPersistentVector, IPersistentSet, IPersistentMap
 and ISeq. Why isn't there a method for IPersistentList?

 Oversight. I'll add it!

 That leaves the question whether there is still any need for the
 clojure.lang.ISeq implementation. At the moment it is used for lists,
 but that is not particularly consistent. I guess I will remove it.

Maybe you should keep it to support custom kinds of sequences that
implement ISeq, but not one of the other interfaces like
IPersistentList.

-- 
R. Mark Volkmann
Object Computing, Inc.

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Konrad Hinsen

On Mar 23, 2009, at 14:26, Mark Volkmann wrote:

 That leaves the question whether there is still any need for the
 clojure.lang.ISeq implementation. At the moment it is used for lists,
 but that is not particularly consistent. I guess I will remove it.

 Maybe you should keep it to support custom kinds of sequences that
 implement ISeq, but not one of the other interfaces like
 IPersistentList.

Among the built-in data types, none does as far as I know. Those who  
implement new data types with ISeq should also provide an  
implementation for fmap, in order to make sure that the return type  
is right and that the semantics are right as well. For example, maps  
implement ISeq, but a default implementation for ISeq would not be  
correct for maps.

Konrad.


--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Jeff Valk

On Mon, 23 Mar 2009 at 03:29, Mark Engelberg wrote:

 But it traverses m twice, which is likely to be less efficient.

I wondered about this too, and actually no. Zipmap is efficient. It constructs 
its return map in a single loop from two lazy seqs. Performance is practically 
identical to the for version:

(defn mapmap1 [f m] (into {} (for [[k v] m] [k (f v)]))) 
(defn mapmap2 [f m] (zipmap (keys m) (map f (vals m

(def m (apply hash-map (range 200)))

(time (def m2 (mapmap1 identity m)))
Elapsed time: 3221.625654 msecs

(time (def m2 (mapmap2 identity m)))
Elapsed time: 3322.947888 msecs

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Jeff Valk

On Mon, 23 Mar 2009 at 07:57, Christophe Grand wrote:

 I prefer the into version which allows to write a mapmap that preserves the
 map type (eg sorted or hash):
 
 (defn mapmap [f m]
   (into (empty m) (for [[k v] m] [k (f v)])))

Agreed. If it were in contrib, this would make most sense.

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Konrad Hinsen

On Mar 23, 2009, at 16:36, Jeff Valk wrote:

 I prefer the into version which allows to write a mapmap that  
 preserves the
 map type (eg sorted or hash):

 (defn mapmap [f m]
   (into (empty m) (for [[k v] m] [k (f v)])))

 Agreed. If it were in contrib, this would make most sense.

It is already in clojure.contrib, with exactly that implementation,  
and for exactly that reason:

http://code.google.com/p/clojure-contrib/source/browse/trunk/src/ 
clojure/contrib/generic/functor.clj

Konrad.




--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Jeff Valk

On Mon, 23 Mar 2009 at 10:48, Konrad Hinsen wrote:

 It is already in clojure.contrib, with exactly that implementation,  
 and for exactly that reason:

Well I'm glad we agree then. :-) And thanks for the pointer.

-Jeff

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread David Sletten


On Mar 23, 2009, at 5:24 AM, Jeff Valk wrote:


 On Mon, 23 Mar 2009 at 03:29, Mark Engelberg wrote:

 But it traverses m twice, which is likely to be less efficient.

 I wondered about this too, and actually no.

I think Mark was referring to the call to 'keys'. But apparently  
Clojure doesn't need to traverse the map to generate the keys?

 Zipmap is efficient. It constructs its return map in a single loop  
 from two lazy seqs.

Not sure what you mean here. It will produce a map from any 2 seqs.  
And it does not generate it lazily--it uses loop. Don't try this at  
home:
(zipmap (map str (iterate inc 1)) (iterate inc 1))


Aloha,
David Sletten


--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-23 Thread Jeff Valk

On Mon, 23 Mar 2009 at 20:10, David Sletten wrote:

 I think Mark was referring to the call to 'keys'. But apparently  
 Clojure doesn't need to traverse the map to generate the keys?

The call to keys just creates a seq. There's no traversal until you consume it.

 Not sure what you mean here. It will produce a map from any 2 seqs.  
 And it does not generate it lazily--it uses loop. Don't try this at  
 home:
 (zipmap (map str (iterate inc 1)) (iterate inc 1))

Indeed that's a good one to avoid. :-) I simply meant that *in the keys/vals 
example above*, using zipmap is approximately as efficient (in time and space) 
as for or reduce, a result I found interesting.

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-22 Thread Kevin Downey

(defn mapmap [fn m]
(into {} (map #(vector (first %) (fn (second %))) m)))

On Sun, Mar 22, 2009 at 1:10 PM, Jon Nadal jon.na...@gmail.com wrote:

 I often need to map a function over the values of a map while
 preserving keys--something like:

 [code]
 (defn mapmap [fn m]
  (let [k (keys m)
        v (map fn (vals m))]
    (zipmap k v)))

 (mapmap inc {:a 0, :b 1})
 [/code]

 Is there a more concise way to do this in Clojure?  If not, is this
 something that might be worth putting in the contrib?

 -Jon

 




-- 
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---



Re: Mapping a function over a map's values

2009-03-22 Thread Timothy Pratley

Golf time!

(defn mapmap [f m]
(into {} (map (fn [[x y]] [x (f y)]) m)))


On Mar 23, 2:51 pm, Kevin Downey redc...@gmail.com wrote:
 (defn mapmap [fn m]
     (into {} (map #(vector (first %) (fn (second %))) m)))

--~--~-~--~~~---~--~~
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
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
-~--~~~~--~~--~--~---