From: Julian Snitow Date: 2003-03-25T15:42:02+09:00 Subject: Re: Iterate over two lists in parallel Jim Weirich wrote: > > [snip!] > > Here's my take on this ... you can find an HTML version (that's a bit > more readable) at http://w3.one.net/~jweirich/talks/same_fringe/ > > [snippety!] Ooh... That is chock full of heady goodness! :-D *throws out my admittedly much-inferior prototypical generator class* Here's something else I've been poking around with. It's a generic external iterator for any collection that supports the :each method. #!/usr/bin/ruby -w class ExternalIterator def initialize(collection) @collection = collection @cont = nil end def get @cont.call if @cont @collection.each { |elem| callcc { |@cont| return elem } } @cont = nil # reset the continuation and return nil end end ex = ExternalIterator.new( ["foo", "bar", "baz", "qux", "florp", "zarg", "narg"] ) while(x = ex.get) puts x end puts "-----" puts ex.get ################################## # Here's the output: foo bar baz qux florp zarg narg ----- foo ################################### Since it uses "each" to generate values, once you've gone through all the values (and the final 'nil'), you can use the same iterator object to iterate through the collection again. This seems a lot less "magical" than your uber-cool Generator class, but with the ability to turn :each "inside out", can anyone think of some problems that still require generators? Also, it just occured to me that it might be more Rubylike to have a mixin method like module Iteration class ExternalIterator # class definition same as above end def iter ExternalIterator.new(self) end end Then you'd just do something like class Array include Iteration end ex = ["foo", "bar", "baz", "qux", "florp", "bzaa", "worble"].iter # then call ex.get whenever you want the next value ###################################