Cайт веб-разработчика, программиста Ruby on Rails ESV Corp. Екатеринбург, Москва, Санкт-Петербург, Новосибирск, Первоуральск

Админка на Ruby on Rails

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