Ruby 2: "Ленивое" вычисление размера (lazy size)
Примеры "ленивого" вычисления размера (lazy size) в Ruby 2, вычисление размера итератора "по требованию".
Enumerator#size может быть вызван для определения размера итератора (количества элементов, возвращаемых итератором) без вычисления всех элементов итератора (если возможно).
(1..100).to_a.permutation(4).size # => 94109400 loop.size # => Float::INFINITY (1..100).drop_while.size # => nil
При создании итераторов с помощью to_enum, Enumerator::New или Enumerator::Lazy::New также возможно определение size:
fib = Enumerator.new(Float::INFINITY) do |y|
a = b = 1
loop do
y << a
a, b = b, b+a
end
end
still_lazy = fib.lazy.take(1_000_000).drop(42)
still_lazy.size # => 1_000_000 - 42
class Enumerable
def skip(every)
unless block_given?
return to_enum(:skip, every) { size && (size+every)/(every + 1) }
end
each_slice(every+1) do |first, *ignore|
yield last
end
end
end
(1..10).skip(3).to_a # => [1, 5, 9]
(1..10).skip(3).size # => 3, without executing the loop
Дополнительные детали и примеры можно посмотреть тут: to_enum