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

On Jun 20, 3:21 pm, Alexander P. [email protected] wrote:

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.

T.

On 6/21/07, Trans [email protected] wrote:

irb(main):002:0> a.reject{|k,v| k==‘foo’ }
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.

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

On 21.06.2007 11:06, Alexander P. wrote:

irb(main):003:0> a.select{|k,v| k==‘baz’ }

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 P. wrote:

Am 21.06.2007 um 11:20 schrieb Robert K.:

=> {“baz”=>“qux”}

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

Hi –

On Thu, 21 Jun 2007, Alexander P. wrote:

irb(main):002:0> a.reject{|k,v| k==‘foo’ }
I have to concur. I’ve never liked that. You’d think there’d be some

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 6/21/07, [email protected] [email protected] 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.

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

Hi –

On Thu, 21 Jun 2007, Robert D. wrote:

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

Am 21.06.2007 um 12:08 schrieb [email protected]:

irb(main):001:0> a = {‘foo’ => ‘bar’, ‘baz’ => ‘qux’}
an array of key-value pairs)?
Is there anybody who can explain, why it had to be implemented
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.

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

Hi –

On Thu, 21 Jun 2007, Alexander P. wrote:

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.

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 6/21/07, [email protected] [email protected] wrote:

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, [email protected] [email protected] wrote:

Hi –

On Thu, 21 Jun 2007, Robert D. 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.

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

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

Hi –

On Thu, 21 Jun 2007, Alexander P. wrote:

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

Hi –

On Thu, 21 Jun 2007, Michael F. wrote:

I fail to see why, could you give an example?
Hash#select the whole time.

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

On Jun 21, 5:37 am, [email protected] 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

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 6/21/07, Alexander P. [email protected] wrote:

There should be a reason Enumerable was introduced as opposed to
include it’s functionality in Array?
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

hi everyone,

I am new to ruby, I want to installed ruby on workstation. But I am not
a
super user and I don’t have the access to /user/local. So I need to
change everything refer to /user/local/ to /home/fixpb.

I try to find every file contain /user/local under ruby directory and
change them . I change the configure.h. I change everything I can find
but
still doesn’t work. I am really frustrated now and need your
help. Thanks!

Regards,
Ting


This e-mail may contain confidential and/or privileged information. If
you
are not the intended recipient (or have received this e-mail in error)
please notify the sender immediately and destroy this e-mail. Any
unauthorized copying, disclosure or distribution of the material in this
e-mail is strictly forbidden.