Reputation: 12971
What is the Python equivalent of the following code in Ruby?
def loop
cont=nil
for i in 1..4
puts i
callcc {|continuation| cont=continuation} if i==2
end
return cont
end
> c=loop
1
2
3
4
> c.call
3
4
Reference: Secrets of lightweight development success, Part 9: Continuations-based frameworks
Upvotes: 7
Views: 2095
Reputation: 87361
There are many weak workarounds which work in special cases (see other answers to this question), but there is no Python language construct which is equivalent to callcc
or which can be used to build something equivalent to callcc
.
You may want to try Stackless Python or the greenlet Python extension, both of which provide coroutines, based on which it is possible to build one-shot continutations, but that's still weaker than Ruby's callcc
(which provides full continuations).
Upvotes: 2
Reputation: 414695
Using generator_tools
(to install: '$ easy_install generator_tools
'):
from generator_tools import copy_generator
def _callg(generator, generator_copy=None):
for _ in generator: # run to the end
pass
if generator_copy is not None:
return lambda: _callg(copy_generator(generator_copy))
def loop(c):
c.next() # advance to yield's expression
return _callg(c, copy_generator(c))
if __name__ == '__main__':
def loop_gen():
i = 1
while i <= 4:
print i
if i == 2:
yield
i += 1
c = loop(loop_gen())
print("c:", c)
for _ in range(2):
print("c():", c())
Output:
1
2
3
4
('c:', <function <lambda> at 0x00A9AC70>)
3
4
('c():', None)
3
4
('c():', None)
Upvotes: 2
Reputation: 414695
def loop():
def f(i, cont=[None]):
for i in range(i, 5):
print i
if i == 2:
cont[0] = lambda i=i+1: f(i)
return cont[0]
return f(1)
if __name__ == '__main__':
c = loop()
c()
Upvotes: 0
Reputation:
take a look at the yield statement to make generators.
I don't speak any ruby, but it seems like you're looking for this:
def loop():
for i in xrange(1,5):
print i
if i == 2:
yield
for i in loop():
print "pass"
Edit: I realize this is basically a specialization of real continuations, but it should be sufficient for most purposes. Use yield
to return the continuation and the .next()
message on the generator (returned by just calling loop()
) to reenter.
Upvotes: 2
Reputation: 994221
The article you quoted contains a link to Continuations Made Simple And Illustrated in the Resources section, which talks about continuations in the Python language.
Upvotes: 5