métodos ruby que producen o devuelven Enumerador


En versiones recientes de Ruby, muchos métodos en Enumerable devuelven un Enumerator cuando son llamados sin un bloque:

[1,2,3,4].map 
#=> #<Enumerator: [1, 2, 3, 4]:map> 
[1,2,3,4].map { |x| x*2 }
#=> [2, 4, 6, 8] 

Quiero hacer lo mismo en mis propios métodos de esta manera:

class Array
  def double(&block)
    # ???
  end
end

arr = [1,2,3,4]

puts "with block: yielding directly"
arr.double { |x| p x } 

puts "without block: returning Enumerator"
enum = arr.double
enum.each { |x| p x }
Author: Doctor Mohawk, 2011-08-25

4 answers

Las bibliotecas del núcleo insertan un guardia return to_enum(:name_of_this_method, arg1, arg2, ..., argn) unless block_given?. En su caso:

class Array
  def double
    return to_enum(:double) unless block_given?
    each { |x| yield 2*x }
  end
end

>> [1, 2, 3].double { |x| puts(x) }
2
4
6 
>> ys = [1, 2, 3].double.select { |x| x > 3 } 
#=> [4, 6]
 27
Author: tokland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-22 21:15:22

Use Enumerador # nuevo :

class Array
  def double(&block)
    Enumerator.new do |y| 
      each do |x| 
        y.yield x*2 
      end 
    end.each(&block)
  end
end
 9
Author: levinalex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-09 15:19:59

Otro enfoque podría ser:

class Array
    def double(&block)
        map {|y| y*2 }.each(&block)
    end
 end
 2
Author: mwolfetech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-25 02:35:37

La manera más fácil para mí

class Array
  def iter
      @lam = lambda {|e| puts e*3}
      each &@lam
  end
end

array = [1,2,3,4,5,6,7]
array.iter

=> 3 6 9 12 15 18 21

 0
Author: mminski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-20 13:38:15