Behaviour of Enumerables reject vs. select mixed into Hash

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

There’s another thing, though, and that is the question of the
symmetry.

I’m not really sure if I’m off-base here, but the first thing you
learn in set theory is that as soon as you see symmetry, you should be
skeptical. Why is that? Well, my cop-out answer is: let the
linguists in the group answer that.

It’s pretty obvious from what everybody says about how Ruby works, and
how best to utilize it, is that it’s a “lambda” … a procedure that
just floats in. But it’s also clear that it’s unclear. It’s a
contradiction.

We ultimately need expressibility in order to have flexibility And
your language of choice gives you a decidability set. I’m using ‘ity’
a lot … sorry.

Mr. David Black once again shows us an interesting perspective:

“Maybe it’s something like: rejecting means subtracting from a thing
that’s already there, but selecting means creating a new collection”

David is smart … the linguists are dumb. Don’t take offense guys :slight_smile:

Todd

Trans wrote:

end

end

The downside here is, it is less efficient and breaks backward
compatibility.

Why the compatibility breakage? The same could be implemented to be
fully backwards compatible:

module Enumerable
  def select(&blk)
    o = respond_to?(:<<) ? self.class.new : Array.new
    each{|*e| o << e if blk[*e]}
  end
end

Daniel

Hi,

At Fri, 22 Jun 2007 06:30:40 +0900,
Trans wrote in [ruby-talk:256489]:

Hmm…well for the first solution, I suppose we need a special
constructor to provide the kind of enumerable result we will be
building. In my example, I used self.class.new, by obviously that’s
not always the case, so the class will need to tell us.

I’d prefer this.

Hi –

On Fri, 22 Jun 2007, Rick DeNatale wrote:

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

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.

Maybe, but I’ll admit that at this stage in this thread, I’m more into
the concrete question of what harm is done by having array be the
common currency. (I’m having trouble following the duck-typing stuff
beyond a certain level of abstraction.) I guess it’s just never
bothered me, which is probably an excessively home-spun way to put it
but it’s about the most rigorous analysis I seem to be up to right now
:slight_smile:

There’s another thing, though, and that is the question of the
symmetry. I’m trying to put my figure on why it doesn’t bother me
that Hash#reject returns a hash and Hash#select returns an array –
that is, I don’t like the fact that Hash#reject is different from
other rejects (at least I somewhat don’t), but in and of itself I
think the fact that reject is not simply defined as !select doesn’t
bother me.

Maybe it’s something like: rejecting means subtracting from a thing
that’s already there, but selecting means creating a new collection –
which of course doesn’t preclude having that collection be a hash, but
does mean that there’s a threshold of deciding what the new collection
will, or could, be.

It would interesting if:

“abc\ndef\nghi”.reject {|s| /abc/.match(s) }

resulted in “def\nghi”…

David

On 6/22/07, Todd B. [email protected] wrote:

David said:

“Maybe it’s something like: rejecting means subtracting from a thing
that’s already there, but selecting means creating a new collection”
No need to create a new collection as an array, no harm to create a
new collection as an array, actually the ongoing discussion about this
point is most interesting and beyond my scope - well I try to learn a
maximum from it.

I should go with David’s approach because I fully understand the
consequences.
But I love Tom’s and Rick’s approach going into unchartered waters…

BTW all this does not answer OP’s, Tom’s and my original concern.
We were talking about Hash#reject and Hash#select not
Enumerable#reject and Enumerable#select, but nobody seems to notice,
sigh :frowning:
This topic would be less difficult to discuss I think.

David is smart … the linguists are dumb. Don’t take offense guys :slight_smile:
Offense, are you kidding? The only thing which bothers me from a set
theory point of view is the symmetry in your statement above.

Honestly Todd if you wanted to make a point I missed it, completely…

Robert

BTW all this does not answer OP’s, Tom’s and my original concern.
We were talking about Hash#reject and Hash#select not
Enumerable#reject and Enumerable#select, but nobody seems to notice,
sigh :frowning:

As I see it, there should be no Hash#reject (nor Array#reject).

Hash (and in fact any class mixing in Enumerable) should be able to
use Enumerable#reject to filter out elements.
That is what Trans’s/Daniels code aims at (hope I am not
misinterpreting them here).

Other than providing exactly this generality for iteration
(==enumeration) methods I see no need to have introduced the class
Enumerable at all.

Sincerely yours
Alex

On 6/22/07, Alexander P. [email protected] wrote:

As I see it, there should be no Hash#reject (nor Array#reject).

Alexander thank you so much :slight_smile:
In the future maybe.
Right now Hash#reject is just the poor man’s implementation of the
concepts which are discussed in this post.
Right now I feel it would be nice if its sibbling Hash#select returned
a Hash too.

Hash (and in fact any class mixing in Enumerable) should be able to
use Enumerable#reject to filter out elements.
That is what Trans’s/Daniels code aims at (hope I am not
misinterpreting them here).
Not at all IMHO

Other than providing exactly this generality for iteration
(==enumeration) methods I see no need to have introduced the class
Enumerable at all.
Sure that is it’s purpose but be careful it is a module.
I do not see any harm in overriding some of the mixed in methods for
special cases like Hash, it is reasonable approach.

Sincerely yours
Alex

Robert

Todd B. wrote:

b/c it’s not unreasonable to see that an Array index is like a Hash
key.

Regardless of what we think is the best, it’s seems pretty clear to me
that the duplicate of the Hash is broken during a delete_if, reject,
select, etc.
That’s one reason I’d like to see more #to_hash methods lying around.

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

On Jun 21, 6:24 pm, [email protected] wrote:

It would interesting if:

“abc\ndef\nghi”.reject {|s| /abc/.match(s) }

resulted in “def\nghi”…

Nice.

I just added

p “abc\ndef\nghi”.e_reject {|s| /abc/.match(s) }

To the end of the enum_test.rb file I posted earlier and that’s exactly
what
I got.


Rick DeNatale

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

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/

On 6/22/07, Robert D. [email protected] wrote:

BTW all this does not answer OP’s, Tom’s and my original concern.
We were talking about Hash#reject and Hash#select not
Enumerable#reject and Enumerable#select, but nobody seems to notice,
sigh :frowning:
This topic would be less difficult to discuss I think.

My hash isn’t your hash. What’s the most generic behavior to expect?

See, you’ve already dismissed me right there, because you’ve decided
if my Hash doesn’t work the way you expect it to, it’s my fault.

Offense, are you kidding? The only thing which bothers me from a set
theory point of view is the symmetry in your statement above.

Honestly Todd if you wanted to make a point I missed it, completely…

That wouldn’t be the first time I’ve been accused of saying a whole
lot of nothin’ :slight_smile:

I stopped talking about Ruby, and started talking instead about
programming in general. I introduced too many things at once. My
bad.

Todd

On 6/22/07, Todd B. [email protected] wrote:

if my Hash doesn’t work the way you expect it to, it’s my fault.
I do not recall having dismissed you at all? I have mad a judgement
about two levels of complexity. If you do not like the behavior of
Hash#reject or Hash#select it might be a good idea to say so, right?
I do not mind at all if somebody says, I like Hash#reject to return a
Set because (this is just an example) etc. etc.

I guess I got confused about who thinks what in this thread :frowning:

I stopped talking about Ruby, and started talking instead about
programming in general. I introduced too many things at once. My
bad.
Indead :wink:

Hi –

On Fri, 22 Jun 2007, Trans wrote:

key. So, for a full parallel we’d need to see something like:
rather than relying on 2-element Array to fulfill the roll. With that
in hand, it would re easy enough to add the #<< method for enumerable
construction.

I don’t think there’s any reason to expect just the value when
iterating through a hash. In fact if you’re using a hash, you
probably have a reason for storing data that way and iterating
pair-wise seems logical to me.

I think it’s a question of how one looks at the underlying types or
behaviors. I don’t think the language has to converge around the
smallest possible number of interfaces. You can look at it the other
way around. It’s useful (extremely) to have hashes, and to iterate
over them in pairs. Enumerable is one way to help introduce that
construct into the language – not a one-stop-shopping hash
implementation, but helpful.

If we then find fault with hash behavior because it’s not in line
precisely with other enumerables, that’s a kind of reverse logic; it’s
a way to talk the language out of having something useful, which I
don’t think is a good idea. Enumerable not only allows but requires
that each class implement #each, and there’s no constraint that every
enumerable class has to yield exactly one value at a time. I’d want
to see more concrete evidence that having hashes and arrays behave
differently is really creating problems before wanting to normalize
them around one construct.

David

On Jun 25, 9:47 am, [email protected] wrote:

pair-wise seems logical to me.
precisely with other enumerables, that’s a kind of reverse logic; it’s
a way to talk the language out of having something useful, which I
don’t think is a good idea. Enumerable not only allows but requires
that each class implement #each, and there’s no constraint that every
enumerable class has to yield exactly one value at a time. I’d want
to see more concrete evidence that having hashes and arrays behave
differently is really creating problems before wanting to normalize
them around one construct.

I don’t necessarily disagree with you. I was following the natural
conclusion of one possible perspective, namely, that the a hash key
corresponds to the array index. It’s one possible way to fix the the
issue posited by the thread. And yet, if our hashes were in fact
ordered, as some have asked for, this assumption would fail. So I’m
not actually for it, but it does offer some contrast.

Consider the order hash perspective. We have an index, plus a key and
a value. So in this case, what exactly are we enumerating? We say
“pairs” as if it is something, but Ruby doesn’t really have such a
thing. The closest we come to is a 2-element array. Perhaps that is
enough, but it’s hardly embraced as such. We see it only in the
iteration of #each if we use a single var. There is no
Hash.new([:a,‘x’],[:b,‘y’]) or hash << [:a,‘x’], etc. If there were, I
think this issue wouldn’t exist. I think Enumerable would a little
more robust, and we could expect that a Hash be returned from #select.
While the 2-element array covers the need, maybe not so much the want,
and we might even consider a real Pair object:

pair = (:a => ‘x’)
pair.key #=> :a
pair.value #=> ‘x’

If we don’t take this perspective (irregardless of an actual Pair
class, or not) I don’t see any good reason to have Enumerable included
in Hash. Just define the desired “enumerating” methods on Hash itself
–just like #reject. But personally, I’d prefer we get Enumerable
right.

And while were on the subject --it seems that’s exactly what we’re
doing with String. I hear that String will no longer be Enumerable in
future Ruby. I really just don’t get this. What’s so problematic with
a default “view” of strings as ordered-sets of characters? All it
requires is the proper definition of #each. Clearly the way things are
now is broken. But does this really require us to scrap String
enumerablity all together? At the very least, how terribly inefficient
it will be to have to convert an string to an array of characters (eg.
bunches of little strings), just to iterate over it.

T.