From: "David A. Black" Date: 2009-08-28T19:11:58+09:00 Subject: Re: #map, #select semantics Hi -- On Fri, 28 Aug 2009, James Coglan wrote: > I imagine this has come up before, though I can't find anything about it. I > was talking to a friend last night who mentioned that in Smalltalk, the > #collect and #select methods (and some others) return the same type as the > object they're called on, and in Ruby they always return an Array, no matter > what the receiver type is. This seems like a good idea to me, though there > are some questions: I'm one of the few, I think, who prefer to get everything back in an array. I like the idea of a uniform structure for result sets from Enumerable operations. Among other things, it's impossible for it to work universally the other way, so it's always going to be "return an array, except for a few special cases." > 1. What do they mean when applied to a Hash? Do you want a list of values, > or keys, or pairs? Or do you want to map each key and value to a different > key and value, and have #map build a Hash for you? If so, how do you > represent that as a return value? Is it [key, value] or {key => value} ? 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. 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 > 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. > 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. David -- David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com Q: What's the best way to get a really solid knowledge of Ruby? A: Come to our Ruby training in Edison, New Jersey, September 14-17! Instructors: David A. Black and Erik Kastner More info and registration: http://rubyurl.com/vmzN