Project

General

Profile

Bug #12466

Updated by nobu (Nobuyoshi Nakada) over 5 years ago

Some methods in `Enumerable` and `Array` yield arrays instead of multiple values, e.g.: 

 ```ruby 
 

     [1, 2, 3, 4].each_cons(2).peek_values #=> [[1, 2]] 
 ``` 

 If `each_cons` would yield multiple values (i.e. `yield 1, 2` instead of `yield [1, 2]`), we could write: 

 ```ruby 
 

     [1, 2, 3, 4].each_cons(2).map(&:quo) #=> [(1/2), (1/3), (1/4)] 
 ``` 

 But currently, this results in an exception and we have to provide a block to achieve the above: 

 ```ruby 
 

     [1, 2, 3, 4].each_cons(2).map { |a, b| a.quo(b) } #=> [(1/2), (2/3), (3/4)] 
 ``` 

 No big deal, but it looks a bit cumbersome (in Ruby terms) and I don't see how the current behavior is preferable. 

 Another example is `reverse_each` which cripples yielded values: 

 ```ruby 
 

     def each_two_values 
   
       return enum_for(__method__) unless block_given? 
   
       yield 1, 2 
   
       yield 2, 3 
   
       yield 3, 4 
 
     end 

 

     each_cons_values.map(&:quo) #=> [(1/2), (2/3), (3/4)] 

 

     each_cons_values.reverse_each.map(&:quo) #=> NoMethodError: undefined method `quo' for [3, 4]:Array 
 ``` 

 Of course, I can easily provide my own implementation: 

 ```ruby 
 

     module Enumerable 
   
       def my_reverse_each 
     
         return enum_for(__method__) unless block_given? 
     
         map { |*values| values }.reverse.each { |values| yield *values } 
   
       end 
 
     end 

 

     each_cons_values.my_reverse_each.map(&:quo) #=> [(3/4), (2/3), (1/2)] 
 ``` 

 But shouldn't this be the default behavior? 

 If an array is actually needed (instead of multiple values), there's `Enumerable#each_entry` which performs the conversion. 

 BTW, other methods _do_ yield multiple values: 

 ```ruby 
 

     %w(a b c).each.with_index(1).peek_values #=> ["a", 1] 
 ``` 

Back