...
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
···
On Jun 21, 2007, at 1:31 PM, Todd Benson wrote:
On 6/21/07, Alexander Presber <aljoscha@weisshuhn.de> wrote: