From: Julian Snitow Date: 2003-03-26T05:44:53+09:00 Subject: Re: External iterators all nice and neat (was: Re: Iterate over two lists in parallel) > Mauricio Fern�ndez wrote: > >> Credits go to Han Holl [67861] for finding this: >> >> batsman@tux-chan:/tmp$ expand -t 2 u.rb >> ######## 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 >> >> class Array; include Iteration; end >> >> arr = ["foo", "bar", "baz", "qux", "florp", "bzaa", "worble"] >> ex = arr.iter >> >> puts ex.get >> puts "---" >> puts ex.get >> puts "***" >> batsman@tux-chan:/tmp$ ruby u.rb >> foo >> --- >> bar >> --- >> baz >> --- >> qux >> --- >> florp >> --- >> bzaa >> --- >> worble >> --- >> nil >> --- >> foo >> *** >> Whoops. On testing it, you're right. The first call *does* spit out the entire list. @hat << Condiments::Ketchup self.eat(@hat) # mmmm... hatty