From: Robert Klemme Date: 2010-08-27T22:30:10+09:00 Subject: Re: Lazy array 2010/8/2 Brian Candler : > Benoit Daloze wrote: >> So, with Enumerator it should be: >> >> even = Enumerator.new { |y| >>   i = 0 >>   loop { >>     y << i >>     i += 2 >>   } >> } >> >> p even.take(5) # => [0, 2, 4, 6, 8] >> >> But that is not really common practice in Ruby (Enumerator for so >> simple things). > > In any case, that Enumerator block form is only syntactic sugar. You can > do the same without using the Enumerator class: > >  even = Object.new >  def even.each(&blk) >    (2..1.0/0).step(2,&blk) >  end >  even.extend Enumerable >  p even.take(5) Even simpler: irb(main):014:0> even = (2..1.0/0).step(2) => # irb(main):015:0> even.take 5 => [2.0, 4.0, 6.0, 8.0, 10.0] irb(main):016:0> even = 2.step(1/0.0, 2) => # irb(main):017:0> even.take 5 => [2.0, 4.0, 6.0, 8.0, 10.0] (pun intended) > In both cases, all you're doing is having 'each' generate an infinite > series, and then truncating it with 'take'. > > This is not useful normally, because you can't chain it - most of the > Enumerable  functions like 'map', 'select' etc collect the full results > into an Array before continuing. > > However, it's quite possible to have these functions process one element > at a time without generating the intermediate arrays, and there is an > implementation of this in the 'facets' library: > > >>> RUBY_VERSION > => "1.8.6" >>> require 'rubygems' > => true >>> require 'facets/enumerator' > => true >>> require 'facets/enumerable/defer' > => true >>> (1..1_000_000_000).defer.select { |i| i % 2 == 0 }.map { |i| i+100 }.take(10).to_a > => [102, 104, 106, 108, 110, 112, 114, 116, 118, 120] > > > Infinite lists are no problem here - each element propagates through the > whole chain before the next. You're processing 'horizontally' rather > than 'vertically'. > > Note that this doesn't use Threads or Fibers, it's efficient, and it > works in ruby 1.8. For the implementation details, see the Denumerator > class. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/