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")


Here's the class I propose as nicer (cause not (less?) buggy):

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
      @outer = nil
    end
    def get
      callcc do |@outer|
        @cont.call if @cont
        @collection.each { |elem|
          callcc { |@cont|
            @outer.call elem
          }
        }
        @cont = nil  # reset the continuation
        @outer.call nil unless @deathThroes
        throw :iter_done # does this still work? TEST ME!!!
      end
    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
***

-- 
 _           _                             
| |__   __ _| |_ ___ _ __ ___   __ _ _ __  
| '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ 
| |_) | (_| | |_\__ \ | | | | | (_| | | | |
|_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_|
	Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Sic transit discus mundi
	-- From the System Administrator's Guide, by Lars Wirzenius