From: jweirich@... Date: 2001-02-17T12:59:46+09:00 Subject: [ruby-talk:11007] Generators (was: RCR Summary 02/16/01 -suspend) Hugh> Icon has the suspend command which allows a function to Hugh> produce a result in the way that return does, but it Hugh> suspends execution so that if the function is called again Hugh> in the same context execution can continue from where the Hugh> suspend left off. It could be considered to be an inside-out Hugh> yield. This is used to create generators rather than Hugh> iterators. It is achieved by leaving the state of the Hugh> function on the stack. How about this ... ---------------------------------------------------------------------- require 'generator' class FibGenerator < Generator def generating_loop generate(1) a, b = 1, 1 loop do generate(b) a, b = b, a+b end end end fib = FibGenerator.new puts fib.next # => 1 puts fib.next # => 1 puts fib.next # => 2 puts fib.next # => 3 puts fib.next # => 5 puts fib.next # => 8 ---------------------------------------------------------------------- Its done with mirrors (and continuations) ... -- File: generator.rb ------------------------------------------------ #!/usr/bin/env ruby # -*- ruby -*- class Generator def initialize do_generation end def next callcc { |here| @main_context = here; @generator_context.call } end private def do_generation callcc { |context| @generator_context = context; return } generating_loop end def generate(value) callcc { |context| @generator_context = context; @main_context.call(value) } end end ----------------------------------------------------------------------