From: Brian Candler Date: 2008-11-04T21:51:11+09:00 Subject: [ruby-core:19695] Re: Odd TypeError in inject (1.9.1 preview 1) On Tue, Nov 04, 2008 at 08:59:08PM +0900, Brian Candler wrote: > But when does #inject actually depend on #next, rather than #each? Also: if I am reading enumerator.c correctly, it seems that #next is implemented as a layer on top of #each (by creating a fiber which in turn calls #each). So would it be true to say that 'each' is the fundamental behaviour of an Enumerator - they would still work even if 'next' were not there? I haven't quite worked out how the block form of enumerator works internally though: class Enumerator def filter(&blk) Enumerator.new do |y| each do |*input| blk.call(y, *input) end end end end (1..10).to_enum. filter { |y,e| puts "Sending #{e.inspect}"; y << e; puts "Sent" }. filter { |y,e| y << e if e % 2 == 0; sleep 0.5 }. filter { |y,e| y << e + 100; sleep 0.5 }. each { |e| puts e } I thought at first there must be Fibers involved somewhere, but now I think it's just yielding: A yields value to B, B yields value to C etc. It's very clever anyway :-) Maybe it would be clearer if the Yielder object implemented #call and #[], like a Proc. Thanks, Brian.