From: Julian Snitow Date: 2003-03-25T17:02:19+09:00 Subject: External iterators all nice and neat (was: Re: Iterate over two lists in parallel) > > Sprry to reply to my own post, but another > small issue is that the generator always > returns nil after it exhausts the collection. > > But what if a collection contains nil values? > > I think I'd like an 'end?' method or something. > At worst, we could define a meta-nil value, but > I'm betting that's not necessary. > > Hal > > I don't know about generators, but for traversing a collection, my iterator externalizer class (which I posted not 15 minutes ago ;-) can handle this with trivial changes. Here it is, ready to eat, just add water, etc. You will not find a nicer iterator class, or I will self.eat(@hat) :-) ######## put this in 'iteration.rb' or something like that ### module Iteration class ExternalIterator def initialize(collection, deathThroes=false) @collection = collection @cont = nil @deathThroes = deathThroes end def get @cont.call if @cont @collection.each { |elem| callcc { |@cont| return elem } } @cont = nil # reset the continuation return nil unless @deathThroes throw :iter_done end end def iter(deathThroes=false) ExternalIterator.new(self, deathThroes) end end ##################################### And here's an example of it in use: ######### foo.rb #################### require 'iteration.rb' class FooCollectionClass # anything with a FooClass#each method include Iteration end myFoo = FooCollectionClass.new iterator = myFoo.iter(true) catch(:iter_done) while(true) puts "The next element is: #{iterator.get}" end end #################################### There. Now Ruby has external iterators. ;-) Julian