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

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

Ruby 2: "Ленивые" итераторы (lazy enumerators)

Примеры использования "ленивых" итераторов (lazy enumerators) в Ruby 2. Итераторы "по требованию".

Enumerable может быть превращен (получен с помощью) в "ленивый" с помощью нового метода Enumerable#lazy:

lines = File.foreach('a_very_large_file')
            .lazy # so we only read the necessary parts!
            .select {|line| line.length < 10 }
            .map(&:chomp)
            .each_slice(3)
            .map {|lines| lines.join(';').downcase }
            .take_while {|line| line.length > 20 }

# => Lazy enumerator, nothing executed yet
lines.first(3) # => Reads the file until it returns 3 elements
               # or until an element of length <= 20 is
               # returned (because of the take_while)

# To consume the enumerable:
lines.to_a  # or...
lines.force # => Reads the file and returns an array
lines.each{|elem| puts elem } # => Reads the file 
                              # and prints the resulting elements

Помните, что lazy будет зачастую более медленным, чем обычная версия итератора (non lazy). Он должен использоваться только тогда, когда это действительно целесообразно, а не только, чтобы избежать создания массива-посредника.

require 'fruity'
r = 1..100
compare do
  lazy   { r.lazy.map(&:to_s).each_cons(2).map(&:join).to_a }
  direct { r.map(&:to_s).each_cons(2).map(&:join) }
end
# => direct is faster than lazy by 2x ± 0.1