On May 1, 2007, at 9:05 AM, Xavier Noria wrote:
> On Apr 30, 2007, at 11:13 AM, Xavier Noria wrote:
>> On Apr 30, 2007, at 3:43 AM, Rick DeNatale wrote:
>>> On 4/28/07, Xavier Noria <fxn / hashref.com> wrote:
>>>> This is a possible approach:
>>>>
>>>>    module Enumerable
>>>>      def each_cycle(window, start=0)
>>>>        (start...length+start).each do |i|
>>>>          yield((i..i+window).map {|n| self[n % length]})
>>>>        end
>>>>      end
>>>>    end
>>>
>>> This method won't work for Enumerables in general, although I  
>>> guess it
>>> does work for Arrays.
>>>
>>> Not all enumerables have one or both length or [] methods.
>>
>> Oh right, thank you. I don't know why ri Enumerable lists length here
>
> It took me a while to discover where that non-core  
> Enumerable#length reported by ri/fri comes from, it is defined by  
> RGL in the file
>
>   rgl-0.2.3/lib/rgl/base.rb
>
> I've learned that ri offers --system the hard way :-).
>
> -- fxn

For those who aren't reading Rick's blog (where this is now in a  
comment):

module Enumerable
   def each_cycle(window, start=0)
     wrap_start = []
     cache = []
     each_with_index do |e,i|
       cache << e
       if i >= start + (window - 1)
         yield cache[start, window]
         cache.shift
       else
         wrap_start << e
       end
     end
     wrap_start.each do |e|
       cache << e
       yield cache[start, window]
       cache.shift
     end
     self
   end
end

Then you can each_cycle anything that is Enumerable, like a Range:
 >> (1..5).each_cycle(3) {|x| p x}
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 1]
[5, 1, 2]
=> 1..5
 >> { 'dog' => 'Rover', 'cat' => 'Mittens', 'fish' =>  
'Goldie' }.each_cycle(2) {|x| p x}
[["cat", "Mittens"], ["fish", "Goldie"]]
[["fish", "Goldie"], ["dog", "Rover"]]
[["dog", "Rover"], ["cat", "Mittens"]]
=> {"cat"=>"Mittens", "fish"=>"Goldie", "dog"=>"Rover"}

-Rob

Rob Biedenharn		http://agileconsultingllc.com
Rob / AgileConsultingLLC.com