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