------ art_604_32898385.1139939660769 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline On 2/14/06, Ross Bamford <rossrt / roscopeco.co.uk> wrote: > ###### Supporting infinite iterators but *not* realtime. ##### > > ### TESTING: davelee_generator.rb > Loaded suite tests > Started > ....E > Finished in 1.075006 seconds. > > 1) Error: > test_realtime(TC_TGenerator): > NoMethodError: undefined method `size' for nil:NilClass > ./davelee_generator.rb:82:in `spent?' > ./davelee_generator.rb:32:in `current' > ./davelee_generator.rb:55:in `next' > tests.rb:179:in `test_realtime' > tests.rb:177:in `test_realtime' > tests.rb:174:in `test_realtime' > > 5 tests, 1557 assertions, 0 failures, 1 errors As James said, thanks for doing this Ross. I hadn't added test_realtime to my test set, but now I have and this bug is fixed. I have attached the fixed version for anyone who cares. For the hell of it, I also optimized by manually inlining some method calls, and eliminating redundant bounds checking. This should now pass all tests and run much faster. These are basically the optimizations: def current - raise EOFError if spent? - @array[@index] + @array.fetch(@index) rescue raise EOFError end def end? - spent? + @index >= @array.size end def next - result = current + begin + result = @array.fetch(@index) + rescue + raise EOFError + end @index += 1 result end def next? - not end? + @index < @array.size end Dave ------ art_604_32898385.1139939660769 Content-Type: application/octet-stream; name=my_generator.rb Content-Transfer-Encoding: 7bit X-Attachment-Id: f_ejoijxq3 Content-Disposition: attachment; filename="my_generator.rb" class MyGenerator def self.stateless(enum il, &block) g ew(enum, &block) g.instance_variable_set(:@stateless, true) g end def initialize(enum il, &block) @index @stateless alse if enum if enum.respond_to? :to_ary @array num.to_ary else block roc { |g| enum.each { |x| g.yield x } } end end if block @array rray.new @block lock [ :current, :end?, :next?, :next ].each do |symbol| method ethod(symbol) metaclass.define_method(symbol) { |*args| fill_from_block; method.call(*args) } end end raise ArgumentError, 'Generate nothing?' unless @array end def current @array.fetch(@index) rescue raise EOFError end def each(&each_block) if @array @array.each(&each_block) else x bject.new def x.yield(value); each_block.call(value); end @block.call(x) end self end def end? @index > array.size end attr_reader :index alias_method :pos, :index def next begin result array.fetch(@index) rescue raise EOFError end @index + result end def next? @index < @array.size end def rewind @index if @block @array rray.new if @block @thread ew_fill_thread end self end def yield(value) @array << value Thread.stop unless @stateless self end private def spent? @index > array.size end def metaclass class << self public_class_method :define_method self end end def new_fill_thread Thread.new { Thread.stop; @block.call(self) } end def fill_from_block return if not spent? or @block_exhausted @thread || ew_fill_thread return unless @thread.alive? @thread.wakeup if @stateless @block_exhausted thread.join(1).nil? else Thread.pass while spent? and @thread.alive? end @thread.stop unless @thread.stop? end end ------ art_604_32898385.1139939660769 Content-Type: text/plain; name=my_generator.diff.txt; charset=us-ascii Content-Transfer-Encoding: 7bit X-Attachment-Id: f_ejoika4l Content-Disposition: attachment; filename="my_generator.diff.txt" --- orig_my_generator.rb 2006-02-14 11:42:28.646227994 -0600 +++ my_generator.rb 2006-02-14 11:48:14.338112433 -0600 @@ -15,21 +15,20 @@ else block roc { |g| enum.each { |x| g.yield x } } end - elsif block + end + if block @array rray.new @block lock - [ :current, :end? ].each do |symbol| + [ :current, :end?, :next?, :next ].each do |symbol| method ethod(symbol) metaclass.define_method(symbol) { |*args| fill_from_block; method.call(*args) } end - else - raise ArgumentError, 'Generate nothing?' end + raise ArgumentError, 'Generate nothing?' unless @array end def current - raise EOFError if spent? - @array[@index] + @array.fetch(@index) rescue raise EOFError end def each(&each_block) @@ -44,20 +43,24 @@ end def end? - spent? + @index > array.size end attr_reader :index alias_method :pos, :index def next - result urrent + begin + result array.fetch(@index) + rescue + raise EOFError + end @index + result end def next? - not end? + @index < @array.size end def rewind @@ -106,4 +109,3 @@ end end - ------ art_604_32898385.1139939660769--