Am 21.06.2007 um 11:20 schrieb Robert Klemme: > On 21.06.2007 11:06, Alexander Presber wrote: >>>> Hello everybody, >>>> >>>> Could you please take a look at the result of the following >>>> statements: >>>> >>>> irb(main):001:0> a = {'foo' => 'bar', 'baz' => 'qux'} >>>> => {"baz"=>"qux", "foo"=>"bar"} >>>> >>>> irb(main):002:0> a.reject{|k,v| k=='foo' } >>>> => {"baz"=>"qux"} >>>> >>>> irb(main):003:0> a.select{|k,v| k=='baz' } >>>> => [["baz", "qux"]] >>>> >>>> The result of the reject statement is clearly sensible: the >>>> original >>>> hash minus the element with the key 'foo'. >>>> But what about select? Shouldn't it return the same hash >>>> (instead of >>>> an array of key-value pairs)? >>> >>> I have to concur. I've never liked that. You'd think there'd be some >>> way to have Enumerable act in accordance with the class it is >>> effecting, rather then dropping to the "LCD" --an array. >> Absolutely. >> But the most baffling to me is, that it does not even act >> _consistently_, see my original examples. >> From a logical point of view (or at least the principle of least >> surprise), selecting some elements should be identical >> to dropping the others. >> Is there anybody who can explain, why it had to be implemented >> that way? >> Is there any chance of that getting changed in the future? Sorry for the empty post, to much clicking without thinking. > The #select in Enumerable can only return a "general" type - in > this case an Array. I see, but isn't that restating the problem? Even though "Programming Ruby" states: [snip] Enumerable#reject: returns an array for all elements of enumObj for which block is false (see also Enumerable#find_all) [/snip], reject _respects_ the class it acts upon in returning a _hash_, not an array. Not so select. Do you see the inconsistency? > Making Enumerable depend on the class is not a good idea IMHO. > Maybe an implementation using #dup would help though... Could you please elaborate into that? I do not understand. > Of course Hash#select could act differently but that a) might hurt > duck typing I fail to see why, could you give an example? > and b) could break existing code. That is true. > Note that you can always do something like > > selected = a_hash.dup.delete_if {|k,v| ... } Not quite. hsh.dup.delete_if is equivalent to hsh.reject, and reject works just fine. And of course I could always use Hash#reject (or hash#delete_if for that matter) instead of Hash#select by just negating the block. But the problem I see lies within the inconsistent return type of Hash#select. I could imagine if one wanted to change that behaviour, the "mixee" class would have to provide certain capabilities to be able to get Enumerable#select, much like objects have to provide an implementation of <=> to get min and max. > Kind regards > > robert Yours truly, Alexander