Generators again

I didn’t understand the Generators using callcc() example I read some
time ago, so I tried it on my own. Maybe my class is more understandable
to others, too…

Somehow my approach reminded me of good old DOS times (cooperative
multitasking implemented in Turbo Pascal)… and in fact, cooperative
multitasking could be implemented by round-robin calling generators.
The usage of that ‘no’ variable might remind of C a bit… (I just
say setjmp/longjmp), although this thing doesn’t seem possible with C:

The stack context will be invalidated if the function which
called setjmp() returns.

(and that’s exactly what those TP hacks did: they used a seperate stack
segment for every cooperative “thread”)

I think this is the main difference between continuations and
setjmp/longjmp.

class Generator
def initialize(&block)
pr = lambda() do |r|
r[0]
block[r]
end
no = 0
callcc() do |cont| @cont = cont end
no += 1
if no == 1 then
pr[lambda() do |v|
@retval = v
get_out_of_here()
end]
lastcont = @cont
@cont = nil
lastcont.call()
end
end
def next!()
raise “read beyond end of generator” if @cont == nil
get_out_of_here()
return nil if @cont == nil
return @retval
end
def get_out_of_here()
no = 0
lastcont = @cont
callcc() do |cont| @cont = cont end
no += 1
if no == 1 then
lastcont.call()
end
end
private :get_out_of_here
end

that’s a generator using another one

def summation(gen)
Generator.new() do |send|
sum = 0
while v = gen.next!()
sum += v
send[sum]
end
end
end

a sample generator

fib = Generator.new() do |send|
a, b = 0, 1
while true
a, b = b, a+b
send[a]
end
end

fibsum = summation(fib)

while true
p fibsum.next!()
end

It’s very nicely explained on RubyFromPython on the Wiki, thanks to
Lyle.

Gavin

···

On Thursday, April 3, 2003, 8:53:21 AM, Rudolf wrote:

I didn’t understand the Generators using callcc() example I read some
time ago, so I tried it on my own. Maybe my class is more understandable
to others, too…