Ruby | Enumerator.new の利用サンプル

# Ruby | Enumerator.new の利用サンプル

## 概要
Ruby　の Enumerator.new の利用サンプルです

## ブロック無し
new(obj, method = :each, *args) -> Enumerator

ブロック無しの Enumerator.new は、あるレシーバーに対して each 以外のメソッドを
使って繰り返すオブジェクトを生成します。

### サンプルコード

~~~ruby
enumerator_methods = Enumerator.methods

slice_methods = Enumerator.new(enumerator_methods, :each_slice, 3)
slice_methods.each do |e|
  print e, "\n"
end
print slice_methods.take(5), "\n"
print slice_methods.map { |a, b, c|[c, b, a] }.take(5), "\n"
~~~

### 出力

~~~ruby
[:allocate, :new, :superclass]
[:freeze, :===, :==]
[:<=>, :<, :<=]
[:>, :>=, :to_s]
[:inspect, :included_modules, :include?]
[:name, :ancestors, :instance_methods]
[:public_instance_methods, :protected_instance_methods, :private_instance_methods]
[:constants, :const_get, :const_set]
[:const_defined?, :const_missing, :class_variables]
[:remove_class_variable, :class_variable_get, :class_variable_set]
[:class_variable_defined?, :public_constant, :private_constant]
[:singleton_class?, :include, :prepend]
[:module_exec, :class_exec, :module_eval]
[:class_eval, :method_defined?, :public_method_defined?]
[:private_method_defined?, :protected_method_defined?, :public_class_method]
[:private_class_method, :autoload, :autoload?]
[:instance_method, :public_instance_method, :nil?]
[:=~, :!~, :eql?]
[:hash, :class, :singleton_class]
[:clone, :dup, :taint]
[:tainted?, :untaint, :untrust]
[:untrusted?, :trust, :frozen?]
[:methods, :singleton_methods, :protected_methods]
[:private_methods, :public_methods, :instance_variables]
[:instance_variable_get, :instance_variable_set, :instance_variable_defined?]
[:remove_instance_variable, :instance_of?, :kind_of?]
[:is_a?, :tap, :send]
[:public_send, :respond_to?, :extend]
[:display, :method, :public_method]
[:singleton_method, :define_singleton_method, :object_id]
[:to_enum, :enum_for, :equal?]
[:!, :!=, :instance_eval]
[:instance_exec, :__send__, :__id__]
[[:allocate, :new, :superclass], [:freeze, :===, :==], [:<=>, :<, :<=], [:>, :>=, :to_s], [:inspect, :included_modules, :include?]]
[[:superclass, :new, :allocate], [:==, :===, :freeze], [:<=, :<, :<=>], [:to_s, :>=, :>], [:include?, :included_modules, :inspect]]
~~~

ただし、ブロック無しでの Enumerator の仕様は非推奨です。
代わりに、 Object#to_enum の利用が推奨されています。

## ブロック無しの代替としての Object#to_enum 

### サンプルコード

~~~ruby
enumerator_methods = Enumerator.methods

slice_methods = enumerator_methods.to_enum(:each_slice, 3)
slice_methods.each do |e|
  print e, "\n"
end
print slice_methods.take(5), "\n"
print slice_methods.map { |a, b, c|[c, b, a] }.take(5), "\n"
~~~

※出力は、 Enumerator.new のブロックなしの例と同じです

## ブロック有り

new(size=nil) {|y| ... } -> Enumerator

ブロックは Enumerator::Yielder オブジェクトを引数にとります。
Yielder オブジェクトに対して << をするたびにブロックが繰り返されます。

### サンプルコード

lorem_ipsums を Enumerator として扱ってみます。
http://ja.wikipedia.org/wiki/Lorem_ipsum

~~~ruby
lorem_ipsums = Enumerator.new do |y|
  lorem_ipsum = <<-EOS
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit, nam.
Aliquam, hic tempora iure quibusdam voluptatibus natus perferendis maiores veritatis.
Doloribus dignissimos odio deleniti dolorum unde doloremque ex eaque voluptates.
Ea placeat dolor quam provident distinctio voluptatibus, fuga ut incidunt.
Ea, reiciendis repudiandae magnam aliquam eum debitis aliquid atque maiores.
  EOS

  lorem_ipsum = lorem_ipsum.gsub(/[\n,\.]/, '').split(' ')
  loop do
    y << lorem_ipsum.shift
    break if lorem_ipsum.empty?
  end
end

print lorem_ipsums, "\n\n"
print lorem_ipsums.to_a, "\n\n"
print lorem_ipsums.take(10), "\n\n"
print lorem_ipsums.map { |e|"「#{e}」" }.take(10), "\n\n"
print lorem_ipsums.take(10).join(', '), "\n\n"
~~~

### 出力

~~~
$ ruby enumerator_with_block.rb
#<Enumerator:0x0000060045f438>

["Lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipisicing", "elit", "Suscipit", "namAliquam", "hic", "tempora", "iure", "quibusdam", "voluptatibus", "natus", "perferendis", "maiores", "veritatisDoloribus", "dignissimos", "odio", "deleniti", "dolorum", "unde", "doloremque", "ex", "eaque", "voluptatesEa", "placeat", "dolor", "quam", "provident", "distinctio", "voluptatibus", "fuga", "ut", "inciduntEa", "reiciendis", "repudiandae", "magnam", "aliquam", "eum", "debitis", "aliquid", "atque", "maiores"]

["Lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipisicing", "elit", "Suscipit", "namAliquam"]

["「Lorem」", "「ipsum」", "「dolor」", "「sit」", "「amet」", "「consectetur」", "「adipisicing」", "「elit」", "「Suscipit」", "「namAliquam」"]

Lorem, ipsum, dolor, sit, amet, consectetur, adipisicing, elit, Suscipit, namAliquam
~~~

## 参照
http://docs.ruby-lang.org/ja/2.1.0/method/Enumerator/s/new.html