Behaviour of Enumerables reject vs. select mixed into Hash

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)?

Thanks for any comments
Sincerely yours
Alexander Presber

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.

T.

···

On Jun 20, 3:21 pm, Alexander Presber <aljos...@weisshuhn.de> 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)?

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

So do I, Do you happen to have some remedies for this in Facets?
I am trying to unify such things in my library, but I am not building
something even close to Factes[1], however if you are interested in
some peaces let me know.

Cheers
Robert

[1] because than I would just use Facets which is really great, but I
want a small library and I want magic dot notation, which are liked by
few only :frowning:

R.

···

On 6/21/07, Trans <transfire@gmail.com> wrote:

On Jun 20, 3:21 pm, Alexander Presber <aljos...@weisshuhn.de> wrote:

T.

--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

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?

Sincerely yours,
Alexander Presber

The #select in Enumerable can only return a "general" type - in this case an Array. Making Enumerable depend on the class is not a good idea IMHO. Maybe an implementation using #dup would help though...

Of course Hash#select could act differently but that a) might hurt duck typing and b) could break existing code. Note that you can always do something like

selected = a_hash.dup.delete_if {|k,v| ... }

Kind regards

  robert

···

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?

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?

The #select in Enumerable can only return a "general" type - in this case an Array. Making Enumerable depend on the class is not a good idea IMHO. Maybe an implementation using #dup would help though...

Of course Hash#select could act differently but that a) might hurt duck typing and b) could break existing code. Note that you can always do something like

selected = a_hash.dup.delete_if {|k,v| ... }

Kind regards

  robert

···

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

···

Am 21.06.2007 um 11:20 schrieb Robert Klemme:

On 21.06.2007 11:06, Alexander Presber wrote:

Hi --

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?

I think Robert's point is that nothing other than a general type makes
sense. For example, if you select from an IO stream, you don't expect
another IO stream.

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?

Hash overrides Enumerable#reject. I'm not sure why, except possibly
because of the relation between reject and delete_if.

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?

Anything that depends on the output having array-like behaviors:

selected = enum.select(&select_block).flatten

David

···

On Thu, 21 Jun 2007, Alexander Presber wrote:

Am 21.06.2007 um 11:20 schrieb Robert Klemme:

On 21.06.2007 11:06, Alexander Presber wrote:

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

That is ok, but we are complaining about

                     hash.select

Please note that the notion of Enumerable#select is erroneous in this
thread, sorry for being blunt Alexander but you were talking about
Hash#select the whole time.

I think this would be a picture case for breaking backwards
compatibility in Ruby2.0
Hash#select --> returning a Hash
and we would live in a better world :wink:
unless you do not like it of course.

In other words it might be interesting to know if people like this
behavior without thinking about backwards compatibility or
implementation details.

Robert

···

On 6/21/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

Hi --

>
> I fail to see why, could you give an example?

Anything that depends on the output having array-like behaviors:

selected = enum.select(&select_block).flatten

--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

Hi --

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?

I think Robert's point is that nothing other than a general type makes
sense. For example, if you select from an IO stream, you don't expect
another IO stream.

Mhm. I thought IO#select is mixed in from the module Kernel, not Enumerable. In this case, select can return whatever Kernel considers appropriate.

I would like to think of the Enumerable mixin as an interface, describing the general concept of "enumerability".
Rejecting and selecting certain elements of an enumerable set certainly belong to this concept.

As I see it, a general recipe for selecting would be:
1) iterate (hence the need for enumerability) vfer the given set and check the return value of the block for each element.
2) if true, keep, otherwise drop
3) return the resulting set, keeping all other properties (including class) intact

Rejecting is just the opposite for 2).

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?

Hash overrides Enumerable#reject. I'm not sure why, except possibly
because of the relation between reject and delete_if.

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?

Anything that depends on the output having array-like behaviors:

selected = enum.select(&select_block).flatten

I don't get what that has to do with duck typing.

The possibility to _flatten_ something requires it to be an Array-duck, not an Enumerable-duck. That is why flatten is part of Array.
Nobody should expect the result of Enumerable#select to be flattenable.

If however there is a sensible way to make the Enumerable an Array (in order to flatten it), you should go:

selected = enum.select(&select_block).to_a.flatten

(note the to_a)

Sincerely yours,
Alex

···

Am 21.06.2007 um 12:08 schrieb dblack@wobblini.net:

On Thu, 21 Jun 2007, Alexander Presber wrote:

Am 21.06.2007 um 11:20 schrieb Robert Klemme:

On 21.06.2007 11:06, Alexander Presber wrote:

Hi --

Hi --

>
> I fail to see why, could you give an example?

Anything that depends on the output having array-like behaviors:

selected = enum.select(&select_block).flatten

That is ok, but we are complaining about

                   hash.select

Please note that the notion of Enumerable#select is erroneous in this
thread, sorry for being blunt Alexander but you were talking about
Hash#select the whole time.

Yes, but making a special case of Hash, as opposed to other
enumerables, is exactly what breaks duck typing. I would actually
prefer to see Hash#reject return an array.

I think this would be a picture case for breaking backwards
compatibility in Ruby2.0
Hash#select --> returning a Hash
and we would live in a better world :wink:
unless you do not like it of course.

In other words it might be interesting to know if people like this
behavior without thinking about backwards compatibility or
implementation details.

I like having arrays be the "common currency" of select operations. I
don't think there's anything that you're prevented from doing as long
as that's the case.

David

···

On Thu, 21 Jun 2007, Robert Dober wrote:

On 6/21/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Hi --

I would like to think of the Enumerable mixin as an interface, describing the general concept of "enumerability".
Rejecting and selecting certain elements of an enumerable set certainly belong to this concept.

As I see it, a general recipe for selecting would be:
1) iterate (hence the need for enumerability) vfer the given set and check the return value of the block for each element.
2) if true, keep, otherwise drop
3) return the resulting set, keeping all other properties (including class) intact

The question, though, is the representation of the "set". Any class
that mixes in Enumerable and defines #each can have a select
operation, and there's no constraint that says that such a class has
to be a collection. So you can't guarantee that the class provides a
container in which an instance can return a smaller version of itself.

Of course Hash#select could act differently but that a) might hurt duck typing

I fail to see why, could you give an example?

Anything that depends on the output having array-like behaviors:

selected = enum.select(&select_block).flatten

I don't get what that has to do with duck typing.

The possibility to _flatten_ something requires it to be an Array-duck, not an Enumerable-duck. That is why flatten is part of Array.
Nobody should expect the result of Enumerable#select to be flattenable.

Well, that's what we're discussing :slight_smile: I expect #select to return an
array, so it's flattenable. But now I think we're going in circles.

David

···

On Thu, 21 Jun 2007, Alexander Presber wrote:

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Hi --

>> Hi --
>>
>> >
>> > I fail to see why, could you give an example?
>>
>> Anything that depends on the output having array-like behaviors:
>>
>> selected = enum.select(&select_block).flatten
> That is ok, but we are complaining about
>
> hash.select
>
> Please note that the notion of Enumerable#select is erroneous in this
> thread, sorry for being blunt Alexander but you were talking about
> Hash#select the whole time.

Yes, but making a special case of Hash, as opposed to other
enumerables, is exactly what breaks duck typing. I would actually
prefer to see Hash#reject return an array.

> I think this would be a picture case for breaking backwards
> compatibility in Ruby2.0
> Hash#select --> returning a Hash
> and we would live in a better world :wink:
> unless you do not like it of course.
>
> In other words it might be interesting to know if people like this
> behavior without thinking about backwards compatibility or
> implementation details.

I like having arrays be the "common currency" of select operations. I
don't think there's anything that you're prevented from doing as long
as that's the case.

So what, making #reject return an Array as well?

···

On 6/21/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

On Thu, 21 Jun 2007, Robert Dober wrote:
> On 6/21/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Sure there is, I do not want to convert Arrays back to Hashes all the
time -- and I am not talking performance.

And why do I have Hash#select anyway in that case? I could very well
use Enumerable#select if I wanted the behavior you have described.

BTW Hash#to_a will not be deprecated I guess :wink:

Robert

···

On 6/21/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

Hi --

On Thu, 21 Jun 2007, Robert Dober wrote:

I like having arrays be the "common currency" of select operations.
don't think there's anything that you're prevented from doing as long
as that's the case.

--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw

The possibility to _flatten_ something requires it to be an Array-duck, not an Enumerable-duck. That is why flatten is part of Array.
Nobody should expect the result of Enumerable#select to be flattenable.

Well, that's what we're discussing :slight_smile: I expect #select to return an
array, so it's flattenable. But now I think we're going in circles.

Why, of all possibities, an Array? Why not an Hash or any other class that mixes in Enumerable?
As I wanted to point out: The Array class is in no way a special Enumerable, but it is treated special by being the return type of some (!) Enumerable operations.

See, not all Enumerables _are_ Arrays, it's the other way around.
It may not make much of a difference in every day coding, but if you don't keep the two apart, then why not drop Enumerable alltogether and always mix Array in instead?
There should be a reason Enumerable was introduced as opposed to include it's functionality in Array?

Yours,
Alexander

The inconsistency of return values between Hash#reject vs. Hash#select
has bothered me for a long time. Above all, I'd want this to be
consistent, but unlike you (and I believe like the majority), I'd like
both to return a Hash.

I'm not really sure how duck typing even enters into it as a serious
concern. The blocks given to reject/select are different based on the
Enumerable type. Consider:

irb(main):017:0> %w{red green blue}.select { |elem| elem.length > 4 }
=> ["green"]
irb(main):018:0> {:red => true, :green => true, :blue => true}.select
{ |elem| elem.length > 4 }
(irb):18: warning: multiple values for a block parameter (2 for 1)
        from (irb):18
(irb):18: warning: multiple values for a block parameter (2 for 1)
        from (irb):18
(irb):18: warning: multiple values for a block parameter (2 for 1)
        from (irb):18
=>

I get an Array from both, which is wonderful if I'm expecting an Array
and I want to flatten the return value or do any other Array-specific
things. The only problem is one array is useless and wrong.

irb(main):019:0> {'red' => true, 'green' => true, 'blue' =>
true}.select { |k,v| k.length > 4 }
=> [["green", true]]

So now I've selected in a more sensible way. The problem here is I
*knew* I was selecting from a Hash and wrote the block accordingly,
but now I have this Array of two-element Arrays back.

This is why I use reject with a negated block.

···

On Jun 21, 5:37 am, dbl...@wobblini.net wrote:

Yes, but making a special case of Hash, as opposed to other
enumerables, is exactly what breaks duck typing. I would actually
prefer to see Hash#reject return an array.

I like having arrays be the "common currency" of select operations. I
don't think there's anything that you're prevented from doing as long
as that's the case.

David

--
-yossef

Hi --

>> > I fail to see why, could you give an example?
>>
>> Anything that depends on the output having array-like behaviors:
>>
>> selected = enum.select(&select_block).flatten
> That is ok, but we are complaining about
>
> hash.select
>
> Please note that the notion of Enumerable#select is erroneous in this
> thread, sorry for being blunt Alexander but you were talking about
> Hash#select the whole time.

Yes, but making a special case of Hash, as opposed to other
enumerables, is exactly what breaks duck typing. I would actually
prefer to see Hash#reject return an array.

It probably won't surprise you but I see it differently. I'd actually
argue that
having an inconsistency between select and reject in the same class is
more harmful to duck-typing than either not returning an array.

Forcing an array return actually is not using duck-typing. At the
very least, it can be seen, as I and it seems Alexandar, Trans and
Robert D do, as forcing a Hash to return an odd duck, or forcing a
Chicken (the Hash) to give birth to a Duck (Array).

The suggestion that Trans made that Enumerable respect the class of
the Module it's included in is not a bad idea IMHO, with the proviso
that it also
needs to respect the meaning of the method as well,
  for example
      (1..5).reject {|i| i == 3}
  would have a hard time returning a Range.

The way this issue was addressed in (ahem) Smalltalk, was to have a
method named species which returned the class to be used for the
result of methods like select, reject, collect.

Here's a sketch of how this COULD be done in Ruby, I named the methods
e_select and e_reject to avoid having Hash override.

rick@frodo:/public/rubyscripts$ cat enumtest.rb
module Enumerable

  def add_from_e_method(elem)
    self << elem
  end

  def species
    self.class
  end

  def e_select
      result = self.species.new
      each {|elem| result.add_from_e_method(elem) if yield elem}
      result
  end

  def e_reject(&blk)
      result = self.species.new
      each {|elem| result.add_from_e_method(elem) unless yield elem}
      result
  end
end

class Hash
  def add_from_e_method(elem)
    self[elem[0]] = elem[1]
  end
end

class Range
  def species
    Array
  end
end

h = {'foo' => 'bar', 'baz' => 'qux'}
p h.e_select {|(k,v)| k == 'foo'}
p h.e_reject {|(k,v)| k == 'foo'}
p (1..10).e_select {|i| (3..4) == i}
p (1..10).e_reject {|i| (3..4) == i}
rick@frodo:/public/rubyscripts$ ruby enumtest.rb
{"foo"=>"bar"}
{"baz"=>"qux"}

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Of course, as they say God is in the details, but this should give an
idea. Were this done in the base, there are probably other and more
efficient
ways to accomplish the same result.

> I think this would be a picture case for breaking backwards
> compatibility in Ruby2.0
> Hash#select --> returning a Hash
> and we would live in a better world :wink:
> unless you do not like it of course.
>
> In other words it might be interesting to know if people like this
> behavior without thinking about backwards compatibility or
> implementation details.

I like having arrays be the "common currency" of select operations. I
don't think there's anything that you're prevented from doing as long
as that's the case.

I know you do, it's consistent with the positions you took back when
we were discussing to_splat. But I think that the case can be made
that preserving the class of these methods is MORE not less
duck-typed.

I just don't buy that you can have any duck you want, as long as it's
an Array is the only or even best choice. If ruby had a more
duck-typed view of collections, it might lead to interesting things.

Of course this is all really just food for thought.

···

On 6/21/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

On Thu, 21 Jun 2007, Robert Dober wrote:
> On 6/21/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Hi --

···

On Thu, 21 Jun 2007, Michael Fellinger wrote:

On 6/21/07, dblack@wobblini.net <dblack@wobblini.net> wrote:

Hi --

On Thu, 21 Jun 2007, Robert Dober wrote:

> On 6/21/07, dblack@wobblini.net <dblack@wobblini.net> wrote:
>> Hi --
>>
>> >
>> > I fail to see why, could you give an example?
>>
>> Anything that depends on the output having array-like behaviors:
>>
>> selected = enum.select(&select_block).flatten
> That is ok, but we are complaining about
>
> hash.select
>
> Please note that the notion of Enumerable#select is erroneous in this
> thread, sorry for being blunt Alexander but you were talking about
> Hash#select the whole time.

Yes, but making a special case of Hash, as opposed to other
enumerables, is exactly what breaks duck typing. I would actually
prefer to see Hash#reject return an array.

> I think this would be a picture case for breaking backwards
> compatibility in Ruby2.0
> Hash#select --> returning a Hash
> and we would live in a better world :wink:
> unless you do not like it of course.
>
> In other words it might be interesting to know if people like this
> behavior without thinking about backwards compatibility or
> implementation details.

I like having arrays be the "common currency" of select operations. I
don't think there's anything that you're prevented from doing as long
as that's the case.

So what, making #reject return an Array as well?

Yes -- see about 18 lines up :slight_smile:

David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Hi --

···

On Thu, 21 Jun 2007, Alexander Presber wrote:

The possibility to _flatten_ something requires it to be an Array-duck, not an Enumerable-duck. That is why flatten is part of Array.
Nobody should expect the result of Enumerable#select to be flattenable.

Well, that's what we're discussing :slight_smile: I expect #select to return an
array, so it's flattenable. But now I think we're going in circles.

Why, of all possibities, an Array? Why not an Hash or any other class that mixes in Enumerable?
As I wanted to point out: The Array class is in no way a special Enumerable, but it is treated special by being the return type of some (!) Enumerable operations.

See, not all Enumerables _are_ Arrays, it's the other way around.
It may not make much of a difference in every day coding, but if you don't keep the two apart, then why not drop Enumerable alltogether and always mix Array in instead?
There should be a reason Enumerable was introduced as opposed to include it's functionality in Array?

But its functionality is only in Array because Array mixes in
Enumerable.

David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242\)
   RUBY FOR RAILS (http://www.manning.com/black\)
* Ruby/Rails training
     & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)

Alexander I agree with your POV, however maybe it would do this
discussion some good to take one step back and look at the greater
picture.

Enumerable is a Mixin based on each and it implements methods like
select, map etc by using the each interface of it's client class. It
very often returns arrays than as it simply cannot do something
different - without creating a revolutionary new concept like an
Iterator but that is OffTopic

You were complaining about Hash#select returning an Array. I complain
about that too but it has nothing to do with Enumerable, Enumerable is
not used, it is implemented in Hash itself.

If we want to discuss if we like or dislike Hash#select returning an
array we shall fear to mention Enumerable as it has nothing to do with
it.
As a matter of fact it would be ridiculous - you have explained that
nicely yourself - to ask Enumerable to return Hashes.

Cheers
Robert

···

On 6/21/07, Alexander Presber <aljoscha@weisshuhn.de> wrote:

There should be a reason Enumerable was introduced as opposed to
include it's functionality in Array?

--
You see things; and you say Why?
But I dream things that never were; and I say Why not?
-- George Bernard Shaw