Thanks for the excellent explanation and code.

One question I have is: why is each_cons inconsistent vis-a-vis
each_slice?  each_slice returns the trailing items, padded with nils -
why doesn't each cons do the same?

On Feb 23, 7:32 pm, Olivier Renaud <o.ren... / laposte.net> wrote:
> It's not important whether the enumeration is done on a File or not. As long
> as the object has a meaningful "each" method, you can enumerate it any way
> you want.
> Your modified enum_const can be accomplished by wrapping the original
> #each_cons in a home-made method. So first, here is a wrapping method that
> just does nothing more than the original :
>
> module Enumerable
>   def each_cons_2(n, &block)
>     each_cons(n) {|a|
>       block.call(a)
>     }
>   end
> end
>
> Then, we just need to get the last value returned by the called block, to be
> able to manually continue the iteration the way you want (adding nils) :
>
> module Enumerable
>   def each_cons_2(n, &block)
>     a = nil
>     each_cons(n) {|a|
>       block.call(a)
>     }
>     (n-1).times { a.shift; a << nil; yield a }
>     nil
>   end
> end
>
> The trick here, is to declare the variable "a" before the block, so that this
> a is the same than the |a| in the block. Doing so, we end up after the block
> with "a" containing the value returned by the last call of the block (ie, the
> array [8,9,10] in your example). Then, we continue the iteration, modifying
> and yielding this array n-1 times.
>
> (1..10).each_cons_2(3) {|a| p a}
> [1, 2, 3]
> [2, 3, 4]
> [3, 4, 5]
> [4, 5, 6]
> [5, 6, 7]
> [6, 7, 8]
> [7, 8, 9]
> [8, 9, 10]
> [9, 10, nil]
> [10, nil, nil]
> => nil
>
> --
> Olivier Renaud