From: Brian Candler Date: 2008-11-02T06:17:39+09:00 Subject: Re: Iterator objects and lazy evaluation David A. Black wrote: > It used to be that you could associate a block with an enumerator > lazily: > >>> e = [1,2,3].enum_for(:map,&lambda {|x| x * 10 }) > => # >>> e.next > => 10 > > and some chaining was possible. But that's gone now. I see. I was wondering about turning the whole thing backwards: pull instead of push. I did some doodling, and after refactoring here's what it boiled down to (ruby1.9.1-preview1): class Enumerator def nmap(&blk) Enumerator.new do |y| begin y << blk[self.next] while true rescue StopIteration end end end def nselect(&blk) Enumerator.new do |y| begin while true val = self.next y << val if blk[val] end rescue StopIteration end end end end # Two variations of the same theme (1..10).each.nselect { |i| i%3 == 2 }.nmap { |i| i+100 }.each { |i| puts i } puts (1..10).each.nselect { |i| i%3 == 2 }.nmap { |i| i+100 }.to_a Now, the intention was as follows: the final method in the chain (each or to_a) repeatedly calls the 'next' method on the item before it, which calls 'next' on the item before it, and so on. It seems to work. I guess Enumerators must use Fibers internally to pause the enumerator block as required? -- Posted via http://www.ruby-forum.com/.