![]() |
Callcc problem in Generator
Hey all,
I was playing with the Generator class the other day and decided I didn't like that you can't break out while iterating through the generator without first having already taken the time to iterate to the element after the one you were at when you decided to break out. The following code shows what I mean. It runs through test_generator() twice, the first with the current implementation of Generator, and the second with a new one I whipped up. It shows that the current implementation takes longer to execute when breaking out early. Also, outside of performance, I don't like that if I were reading a stream of data and decided to break out, it would read one too many lines--kind of an ugly side-effect. Unfortunately, there's a significant bug in my version that I been trying to crack all night and I can't figure it out for the life of me. I want to be able to start iterating, then midway through, call rewind(), and then start iterating through again. When I do that, it leaves the stack in an odd place, and when I call each(), it will make it all the way to the end then get caught in an infinite loop inside next?(). So I guess my question is, if you create a continuation with callcc() and then decide never to call that continuation, is there some way to unwind the stack? Thanks, Greg require 'generator' def test_generator() timeStart = Time.now puts "start constructing at #{Time.now - timeStart}" gen = Generator.new do |g| for num in [1,2,3,4,5] sleep(3) g.yield(num) end end puts "finished constructing at #{Time.now - timeStart}" puts "getting first element at #{Time.now - timeStart}" for num in gen puts num break if num == 3 puts "getting next element at #{Time.now - timeStart}" end puts "done at #{Time.now - timeStart}" puts "\n\n" end puts "Ruby's Generator" test_generator() class EndOfGenerator < Exception end class Generator def initialize(&closure) @closure = closure return rewind() end def each() rewind() while self.next?() yield self.next() end return self end def rewind() @closureEntryPoint = nil @currentElement = nil @nextElement = nil @position = -1 #self.next?() return self end def pos() return @position end def current() if @currentElement == nil begin self.next() @nextElement = @currentElement rescue EndOfGenerator end end return @currentElement end def next?() return true if @nextElement begin @nextElement = self.next() return true rescue EndOfGenerator return false end end def end?() return !self.next?() end def next() if @nextElement @currentElement = @nextElement else @currentElement = callcc do |cc| @generatorEntryPoint = cc if @closureEntryPoint == nil @closure.call(self) raise EndOfGenerator.new() else @closureEntryPoint.call() end end @position += 1 end @nextElement = nil return @currentElement end def yield(obj) return callcc do |cc| @closureEntryPoint = cc @generatorEntryPoint.call(obj) end end end puts "Corrected generator" test_generator() |
| All times are GMT. The time now is 06:37 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.