On Jun 21, 2007, at 1:31 PM, Todd Benson wrote: > On 6/21/07, Alexander Presber <aljoscha / weisshuhn.de> wrote: >> ... >> Making Enumerable behave more agnostic to the class it is mixed in >> (by letting the class itself provide a method to add an "element" to >> an instance of itself, Enumerable becomes truly mixable into anything >> that provides "each" and "<<". >> Then doing reject on any class that mixes in Enumerable will yield a >> filtered instance of that class, not Array. >> >> That said - I think there should be no such thing as TomsEnum or any >> special implementation. >> Enumerable is the place to define methods for all things containing >> enumerable elements. >> >> >> >> >> The other option would require an #each_assoc method (maybe assoc >> >> isn't the best term, but anyhow...) >> >> >> >> module Enumerable >> >> def select_assoc(&blk) >> >> h = {} >> >> each_assoc{|k,v| h[k]=v if blk[k,v]} >> >> h >> >> end >> >> end >> >> >> >> The downside here of course, is twice the number of Enumerable >> >> methods. >> > And although I cannot imagine a case, how do we know that there are >> > not Enumerables that take three or fourtytwo params ;). >> > After all Enumerable is a Mixin and we have to be prepared that >> it be >> > mixed in, right? >> >> Yes, one could impossibly provide for all possible Mixees like this. >> >> Yours, >> Alex > > 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 > 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. > > ... > > Todd What no one seems to have (directly) focussed on is that Hash#each gives two-element [k,v] arrays back as the content. Is this what Alexander Presber means with: >> Enumerable is the place to define methods for all things containing >> enumerable elements. It's how you define the elements that are enumerable. Hash#each_key, Hash#each_value, and Hash#each_pair make this explicit. Hash#each being simply Hash#each_pair (the documentation says it's the other way around, but if they're synonyms what does it matter) makes the definition of a "pair" or more explicitly "key-value pair" a good place to focus. Perhaps if a Hash was a collection of "entries" so #each returned something closer to {k=>v} rather than an array. s = [1, 2, 3] r = s.class.new s.each {|e| r << e} r => [1, 2, 3] Currently, if we replace the value of the array s with a hash { 1 => 'uno', 2 => 'dos', 3 => 'tres' } you'd need something like: class Hash alias_method :<<, :update alias_method :orig_each, :each def each orig_each {|k,v| yield({k=>v}) } end end to get a similar result: s={1=>'uno',2=>'dos',3=>'tres'} r = s.class.new s.each {|e| r << e} r => {1=>"uno", 2=>"dos", 3=>"tres"} if the notation to "unpack" block arguments .each {|(k,v)| ... } would pick apart a hash entry like {k=>v} the same way that it would [k,v] (which, of course, doesn't actually need the parentheses), then the "syntactic compatibility" would be close enough for my brain, eyes, and fingers. I think that the arity of block that each_pair expects should remain 2 and each_pair should yield([k,v]) (so the meaning of "pair" for English-speakers is maintained -- I realize I being anglophilic here). The arity of the block expected by #each would be 1. It seems to me that you'd also get "benefits" like. {1=>"uno", 2=>"dos", 3=>"tres"}.sort_by {|k,v| v} => [{2=>"dos"}, {3=>"tres"}, {1=>"uno"}] Since you'd clearly need to transform to a type that was ordered if you wanted to "sort" an unordered Hash. And if there were a #<=> defined for a Hash entry, you could just use #sort. This is clearly a slippery slope because you'd then have to redefine Hash#shift to give {k=>v} rather than [k,v] also. You'd almost certainly want something like #first and #last to give the key and value from {k=>v} like they'd pull those parts from [k,v]. [Blah! I took too long to answer and Alex(ander) got another response to Todd in with some of the same ideas, but I decided to post anyway.] -Rob Rob Biedenharn http://agileconsultingllc.com Rob / AgileConsultingLLC.com