This blog is part of our Ruby 2.4 series.
Enumerable#chunk method can be used on enumerator object to group consecutive items based on the value returned from the block passed to it.
1 2[1, 4, 7, 10, 2, 6, 15].chunk { |item| item > 5 }.each { |values| p values } 3 4=> [false, [1, 4]] 5[true, [7, 10]] 6[false, [2]] 7[true, [6, 15]] 8
Prior to Ruby 2.4, passing a block to chunk method was must.
1 2array = [1,2,3,4,5,6] 3array.chunk 4 5=> ArgumentError: no block given 6
Enumerable#chunk without block in Ruby 2.4
In Ruby 2.4, we will be able to use chunk without passing block. It just returns the enumerator object which we can use to chain further operations.
1 2array = [1,2,3,4,5,6] 3array.chunk 4 5=> <Enumerator: [1, 2, 3, 4, 5, 6]:chunk> 6
Reasons for this change
Let's take the case of listing consecutive integers in an array of ranges.
1 2# Before Ruby 2.4 3 4integers = [1,2,4,5,6,7,9,13] 5 6integers.enum_for(:chunk).with_index { |x, idx| x - idx }.map do |diff, group| 7 [group.first, group.last] 8end 9 10=> [[1,2],[4,7],[9,9],[13,13]] 11
We had to use enum_for here as chunk can't be called without block.
enum_for creates a new enumerator object which will enumerate by calling the method passed to it. In this case the method passed was chunk.
With Ruby 2.4, we can use chunk method directly without using enum_for as it does not require a block to be passed.
1 2# Ruby 2.4 3 4integers = [1,2,4,5,6,7,9,13] 5 6integers.chunk.with_index { |x, idx| x - idx }.map do |diff, group| 7 [group.first, group.last] 8end 9 10=> [[1,2],[4,7],[9,9],[13,13]] 11