If you are a Ruby programmer and you haven’t found a use for Enumerable#each_cons, you just probably haven’t thought about it yet.
— Michael Feathers (@mfeathers)
Well, Ruby is a great language, with a lot of nice surprises tucked away in its dustier corners. The Enumerator class is certainly a common one to reach for when solving problems, but I can honestly say I’ve never needed the Enumerator#each_cons method. After seeing Michael’s tweet, I took a look to see what it does.
The method definition says:
each_cons(n) {...} → nil
each_cons(n) → an_enumerator
Iterates the given block for each array of consecutive <n> elements.
If no block is given, returns an enumerator.
On the surface, it looks like just another way to specify an array
slice. Not so! The #each_slice
method will return chunks of n
elements, but #each_cons
actually returns a sliding window of
elements. Consider the following:
1 2 3 4 5 6 7 8 9 10 

What’s interesting is that the output of #each_slice
will return
nonoverlapping blocks of Enumerable elements, while #each_cons
shows
all possible consecutive blocks from the Enumerable object. It’s as if
the method slides a window of n elements across the length of an
array, moving the starting index of the window up by exactly one element
each time.
Another nonobvious property is that #each_slice
will happily return
an array smaller than the specified value if it runs out of Enumerable
elements to process, while #each_cons
always returns the requested
length unless it returns nil. For example:
1 2 3 4 5 6 7 8 

Even though the specified Range object is not a multiple of five, our example always returns exactly five elements in each array unless there are less than five total elements in the Range. Nifty!
So, What’s It Good For?
Maybe it’s a failure of imagination on my part, but I can’t actually think of a useful application for this method outside of validating Fibonacci sequences.
1 2 

If you want to know all the various ways that elements of an array can be arranged together, Array#combination or Array#permutation seem like they’d be more intrinsically useful. On the other hand, this method is clearly intended for segmenting an Enumerable, but the realworld usefulness of doing so eludes me.
I always enjoy exploring odd corners of Ruby, and hope you’ve enjoyed
this little tour of Enumerable#each_cons
. If you can think of a
practical use for it, please leave a comment below.