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