Хотя это довольно удобно для создания бесконечных списков и ленивых итераторов, мое любимое использование - обернуть существующий Enumerable дополнительными функциями (любым перечислимым, без необходимости знать, что это на самом деле, является ли он бесконечным или нет).и т.д.).
Тривиальным примером будет реализация метода each_with_index
(или, в более общем смысле, метода with_index
):
module Enumerable
def my_with_index
Enumerator.new do |yielder|
i = 0
self.each do |e|
yielder.yield e, i
i += 1
end
end
end
def my_each_with_index
self.my_with_index.each do |e, i|
yield e, i
end
end
end
[:foo, :bar, :baz].my_each_with_index do |e,i|
puts "#{i}: #{e}"
end
#=>0: foo
#=>1: bar
#=>2: baz
Теперь давайте расширим то, что еще не реализовано в corelib:), например, циклическое присваивание значения из данного массива каждому перечисляемому элементу (скажем, для строк таблицы раскраски):
module Enumerable
def with_cycle values
Enumerator.new do |yielder|
self.each do |e|
v = values.shift
yielder.yield e, v
values.push v
end
end
end
end
p (1..10).with_cycle([:red, :green, :blue]).to_a # works with any Enumerable, such as Range
#=>[[1, :red], [2, :green], [3, :blue], [4, :red], [5, :green], [6, :blue], [7, :red], [8, :green], [9, :blue], [10, :red]]
Весь смысл в том, что эти методы возвращают Enumerator
, который затем объединяется сОбычные перечисляемые методы, такие как select
, map
, inject
и т. д.