注意:对于下面yielder这个对象,文档也没有说明,我自己的理解就是,该对象有一个实例方法,来指定迭代的内容。
triangular_number = Enumerator.new do |yielder|
number = 0
count = 1
loop do
number += count
count += 1
yielder.yield number
end
end
require 'pp'
5.times do
pp triangular_number.next
end
返回结果如下:
1
3
6
10
15
Enumerator对象实例可以完整的使用maxin Enumerable的所有方法,例如:to_a,first,take...
pp triangular_number.first 5
[1, 3, 6, 10, 15]
下面的例子:
fib = Enumerator.new do |yielder|
a = 1
b = 1
loop do
yielder.yield a
a , b = b , a + b
end
end
require 'pp'
#5.times { pp fib.next }
#pp fib.take(10)
#我们通过Enumerator创建一个无限枚举对象,当然我们也可以
#传递一个Block生成一个新的Enumerator
def infinite_sleect(enum, &block)
Enumerator.new do |yielder|
enum.each do |value|
yielder.yield value if block.call(value)
end
end
end
pp infinite_sleect(fib) { |value| value % 5 ==0 }.first(10)
下面的例子:
fib = Enumerator.new do |yielder|
a = 1
b = 1
loop do
yielder.yield a
a , b = b , a + b
end
end
require 'pp'
#更有意思的是我们可以在类Enumerator中定义一个方法,来继续迭代自身
class Enumerator
def infinite_sleect(&block)
Enumerator.new do |yielder|
self.each do |value|
yielder.yield value if block.call(value)
end
end
end
end
pp fib
.infinite_sleect { |value| value % 2 == 0 }
.infinite_sleect { |value| value % 4 == 0 }
.first(10)