From: "Aleksi Niemelä" Date: 2000-10-05T08:00:40+09:00 Subject: [ruby-talk:5293] RE: RFC: Enumerable#every(n) Hello Musha-san, > Enumerable#every(n) > > Returns an Enumerable object that yields the iterator block for > every elements. The block is yielded with arguments for > each, and if the number of elements are short by for the last > yield, nil's are filled as necessary. I like the functionality very much. But I have to say I didn't understand the real semantics when I briefly tried to follow discussion at ruby-dev, nor when I read the source code (I just got confused, I think your sources are the normal Ruby source quality, so nothing wrong with them). Then I read this explanation, and I'm just probably quite tired, but didn't understand it even then. Then I remembered the use of arrays in the sources, and the second example cleared up things. If I may try to describe the functionality it'd be like this: Enumerable#every(n) Returns an Every object, which implements Enumerable interface. The Every object has an reference to the receiver of this method call, and specifies the count of elements of original object to be grouped. Every#each Iterates through the referenced object by calling it's method each and gathering elements. After elements gathered in an array it yields the array to the associated iterator block. If the last group doesn't get filled from original's enumeration, it's padded with nils. Thus Every#each regroups original Enumerable#each results. Example: every = ["1", "a", "2", "b", "3"].every(2) p every every.each {|ary| p ary} Outputs: # ["1", "a"] ["2", "b"] ["3", nil] As all methods defined in the module Enumerable rely on method each which the class have to provide, everything in Enumerable is applicable to an Every object. Example: # print first grouping which first element # contains some text ary = ["1", "a", "2", "b", "3"] p ary.every(3).find {|ary| ary[0] =~ /\w+/ } Outputs: ["b", "3", nil] > 1) Is the name "every" appropriate? I think Every, and methods, would be better named as Group. Thus leading to $ ruby -e 'p (("A".."Z").group(4).find_all{|i| ... > 2) Is it worth being integrated to the standard Enumerable class? Can't say for sure. I think it is, as there are some happy side-effects if it's redefined. Someone remembers a ruby-talk thread where we discussed how to gather all the output of an iterator into an array. Well, provided we know how much we should get we could say obj.group(this_many).each {|ary_of_all_elements_gathered| ... } Of course we could improve this. As there's already Enumerable#to_a we can say the above example better as all_elements = obj.group(this_many).to_a If there's a way to express we want the Group object gather everything it would be even simpler all_elements = obj.group.to_a # def group(n=nil) And for convenience we would probably get all_elements = obj.suck_until_theres_nothing_but_an_array_in_the_end Anyway, the trick to get Every work like this is to be able to pass every_each_i wrapped into a proc, which could then be associated with a method. Or maybe the Proc or Method which should be collected could be provided to Every object. def get_ten_random_numbers 10.times { yield rand; } end nums_in_5_groups = Every.new(5, self.method("get_ten_random_numbers")) This side note is no real proposition, just a reminder that there has been need for something like this earlier; then they just didn't realize they'd get something better :). Even in current form I'd welcome this new functionality, as it's no massive overkill, just a small creature which does just one thing and does it well. - Aleksi