Mauricio Fern?ndez wrote:
> On Tue, Mar 25, 2003 at 05:02:19PM +0900, Julian Snitow wrote:
> 
>>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
> 
> 
> 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
> ***
> 
> I guess this means that...
> 
>   Object.const_get("Julian Snitow").send("eat!".intern, "hat")

Not quite. ;)  Array#shift returns nil when the collection is empty, so 
I used that behavior, too.  So once you've got nil, the iteration is 
over, and any further calls to ex.get will be those of a new iteration.