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