# Ruby/Python Continuations: Turning a block callback into a r

**URL:** <https://www.ruby-forum.com/t/ruby-python-continuations-turning-a-block-callback-into-a-r/66198>\
**Category:** Ruby\
**Created:** [February 12, 2006, 9:18pm UTC](https://www.ruby-forum.com/t/ruby-python-continuations-turning-a-block-callback-into-a-r/66198 "2006-02-12T21:18:38Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![robert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/e95f7d/32.png) [@robert](https://www.ruby-forum.com/u/robert)\
**Post date:** [February 12, 2006, 9:18pm UTC](https://www.ruby-forum.com/t/ruby-python-continuations-turning-a-block-callback-into-a-r/66198/1 "2006-02-12T21:18:38Z")

</div>

After failing on a yield/iterator-continuation problem in Python (see  
below) I tried the Ruby (1.8.2) language first time on that construct:  
The example tries to convert a block callback interface  
(Net::FTP.retrbinary) into a read()-like iterator function in order to  
virtualize the existing FTP class as kind of file system. 4 bytes max  
per read in this first simple test below. But it fails on the second  
continuation with ThreadError after this second continuation really  
executing!? Any ideas how to make this work/correct?

(The question is not about the specific FTP example as it - e.g. about a  
rewrite of FTP/retrbinary or use of OS tricks, real threads with polling  
etc… - but about the continuation language trick to get the execution  
flow right in order to turn any callback interface into an “enslaved  
callable iterator”. Python can do such things in simple situations with  
yield-generator functions/iter.next()… But Python obviously fails by a  
hair when there is a function-context barrier for “yield”. Ruby’s  
block-yield-mechanism seems to not at all have the power of real  
generator-continuation as in Python, but in principle only to be that  
what a normal callback would be in Python. Yet “callcc” seemes to be  
promising - I thought so far ☹ )

=== Ruby callcc Pattern : execution fails with ThreadError!? ===========  
require ‘net/ftp’  
module Net

class FTPFile  
def initialize(ftp,path)  
@ftp = ftp  
@path=path  
@flag=true  
@iter=nil  
end  
def read  
if @iter  
puts “@iter.call”  
@iter.call  
else  
puts "RETR "+@path  
@ftp.retrbinary("RETR "+@path,4) do |block|  
print “CALLBACK “,block,”\n”  
callcc{|@iter| @flag=true}  
if @flag  
@flag=false  
return block  
end  
end  
end  
end  
end

end

ftp = Net::FTP.new(“localhost”,‘user’,‘pass’)  
ff = Net::FTPFile.new(ftp,‘data.txt’)  
puts ff.read()  
puts ff.read()

=== Output/Error ====

vs:~/test$ ruby ftpfile.rb  
RETR data.txt  
CALLBACK robe  
robe  
@iter.call  
CALLBACK rt

/usr/lib/ruby/1.8/monitor.rb:259:in `mon_check_owner': current thread not owner (ThreadError) from /usr/lib/ruby/1.8/monitor.rb:211:in`mon\_exit’  
from /usr/lib/ruby/1.8/monitor.rb:231:in `synchronize' from /usr/lib/ruby/1.8/net/ftp.rb:399:in`retrbinary’  
from ftpfile.rb:17:in `read’  
from ftpfile.rb:33  
vs:~/test$

# === Python Pattern : I cannot write down the idea because of a barrier

#### I tried a pattern like:

```
 ....
 def open(self,ftppath,mode='rb'):
     class FTPFile:
         ...
         def iter_retr()
             ...
             def callback(blk):
                 how-to-yield-from-here-as-iter_retr blk???
             self.ftp.retrbinary("RETR %s" % self.relpath,callback)
         def read(self, bytes=-1):
             ...
             self.buf+=self.iter.next()
             ...
         ...
     ....

```

=====

Robert
