From: Rick DeNatale Date: 2009-08-28T22:51:54+09:00 Subject: Re: #map, #select semantics On Fri, Aug 28, 2009 at 6:11 AM, David A. Black wrote: > Hash#select and #reject return hashes in 1.9: > >>> h = { 1 => 2, 3 => 4, 5 => 6 } > > => {1=>2, 3=>4, 5=>6} >>> >>> h.select {|k,v| k > 1 } > > => {3=>4, 5=>6} > > #map returns an array. I don't think it can be otherwise, since you're > only returning one value from the code block. Both of these are more like Smalltalk. As I pointed out in another posting to this thread, in the second case Smalltalk would return a Bag of values from the receiver. I honestly can't recall ever using map with a Dictionary in Smalltalk, or with a Hash in Ruby for that matter. > Of course it would be > possible to write something like this: > > module Enumerable >  def map2hash >    res = {} >    each do |k,v| >      res[k] = yield(v) >    end >    res >  end > end It's trickier coming up with a map for Hash which enumerates over the key,value pairs and allows the block to return a new key,value pair, what do you do if there are duplicate keys? Smalltalk finessed that question. > >> 2. Is part of the contract of #map that you get back a collection of the >> same size as the input? If so, what happens if you #map a Set and produce >> duplicates? The output will be smaller than the input (similarly for hash >> key collisions). Certainly from an FP viewpoint, a map is a one-to-one >> transform from input to output values, so it would seem logical to have as >> many output values as input values. > > I think any quasi-mappish operation that departs from real map > semantics would have to be a different method. Mapping an enumerable > through a function to an array is just too basic and too useful not to > be available. I think there are two sides to that. If you think of the world of collections primarily as arrays, then this makes sense. OTOH, if you think of collections more abstractly, then having map on a Set return a Set which might be smaller because of duplication in the results of the block is useful as well, and if you want the array behavior you can make an Array from the set ant then map that. >> 3. There is no uniform method for adding items to a collection. We have >> Array#<<, Hash#[]=, Set#add and Set#add?. For linked lists, adding to the >> collection would involve changing pointers on existing members of the >> collection. Is it possible to come up with a single method/message whose >> role is to provide a uniform way to add something to any collection? > > You could try -- it should be implementable in Ruby, at least for > proof of concept. The difficulty is that for some Ruby classes, I'm thinking of Hash in particular here, it's not clear what an element is, in Smalltalk every collection is a collection of elements, with Dictionary elements being key-value associations. -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale