From: Todd Benson Date: 2007-06-22T03:43:01+09:00 Subject: Re: Behaviour of Enumerables reject vs. select mixed into Hash On 6/21/07, Alexander Presber wrote: > Am 21.06.2007 um 19:31 schrieb Todd Benson: > > > A duck is a bird. It doesn't behave exactly like every other bird you > > know about. But you can be relatively certain it has wings. > > I am on your side up to here :-) > > > I suspect the least common denominator return of the object is > > there for > > several reasons, including testing, ease of the ruby language > > development, etc. Why the difference for the Hash returning a > > different object between select and reject? I think it's one of those > > oversight things. > > > > Thinking about LCD another way, why is it that "13s".to_i gives me 13? > > 13 is a good result for "13s".to_i, I couldn't come up with a better > one: You ask the string class to > give you an integer (hence the _i) for a certain string and it does > so in an (arguably) optimal way. > > However, [["baz", "qux"]] is not a good result for > {'foo' => 'bar', 'baz' => 'qux'}.select{|k,v| k=='baz' }, > {'baz' => 'qux'} would be much more sensible. > > Can you see the difference? Sure. Why does [1,2,3].delete(3) return the integer 3 instead of the array? It's just semantics. What you think is a duck is not necessarily what somebody else thinks is a duck. > > > Because it _mostly_ is an integer. So, if I have an Enumerable > > object that I perform some operation on; where does it say in > > duck-typing that I should get an Enumerable object back? > > It is not duck-typing promising me an enumerable. > When calling enum.to_a I _expect_ an Array and nothing else. I don't know what you expect, but I think you expect some semblance of continuity (in english). > It is the _concept_ of "select" that promises a Hash when calling it > on a Hash. _concept_ of "select", again that's what you think it should mean. > Enumerability (and therefore the possibility to _iterate_) just > happens to be a requirement for selecting. > > But as Yossef pointed out already, it doesn't have to do all that > much with duck typing. > Duck typing allows me to let a class share methods with other classes > (provided some conditions on these classes are met) > without specifying the exact classes beforehand. > A la: This is an "enumerable", it must be able to "select" some of > its elements with a specified rule. > > You seem to imply, that in order to allow for classes to mix > Enumerable in, we would have to accept > to get Arrays back for filter operations as a "least common > denominator". Okay, here's where you make a good point. Array actually is _not_ the LCD of an Enumerable object logistically. But it may very well be the LCD at the bottom level; the inner workings of Ruby. That's a bold thing for me to say because I haven't read the Ruby source code yet. > I disagree, and in fact that is the whole point of my first post. > > By adding a second requirement to the class that wants to mix in > Enumerable (implementing an "appendElement" method or, as Array calls > it already "<<") > we can let go of that arbitrary and confusing "LCD": Any filtering > method returns the class of the object that gets filtered. > > > Just by its very nature, duck-typing will forever be laden with > > inconsistencies. > > I do not think so. If you can have objects be inconsistent, your "pragmatic program" means naught to me unless I already know where you're coming from -- cost of flexibility argument. > > The LCD object return is a simple way around it. I > > agree with the general consensus here that #select and #reject should > > return the same way for a Hash, but you have to keep in mind that > > writing a pragmatic language that does what you want is like trying to > > assume everything about you as a programmer before you start typing. > > To do that, maybe the designer should be using the LCD for pretty much > > everything :) > > I don not agree. I have not yet heard of the concept of "LCD" being > necessary to work with duck typing. I didn't say necessary. I guess the point is moot because we seem to all agree that #select and #reject should be polar opposites (I'm leaving out 3-valued logic when I say that). I was just pointing out that reject and select may not mean the same thing to you as it does to me. When you don't know what the person expects as a return value, you give them something that you yourself might expect. Todd