Python equivalente de continuações com rubi
-
10-07-2019 - |
Pergunta
O que é o equivalente Python da seguinte código em 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
Referência: Segredos do sucesso do desenvolvimento leve, Part 9: Continuations baseado estruturas
Solução
O artigo que você citou contém um link para Continuations feito simples e Illustrated na seção de Recursos, que fala sobre continuações na linguagem Python.
Outras dicas
dar uma olhada na rendimento declaração para fazer geradores.
eu não falo qualquer rubi, mas parece que você está olhando para isso:
def loop():
for i in xrange(1,5):
print i
if i == 2:
yield
for i in loop():
print "pass"
Edit: Sei que este é, basicamente, uma especialização de continuações reais, mas deve ser suficiente para a maioria dos propósitos. Use yield
para retornar a continuação ea mensagem .next()
no gerador (retornado por apenas chamando loop()
) para reinserir.
Usando generator_tools
(para instalar: '$ 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)
Existem muitas soluções fracas que trabalham em casos especiais (ver outras respostas a esta pergunta), mas não há nenhuma construção da linguagem Python, que é equivalente a callcc
ou que pode ser usado para construir algo equivalente a callcc
.
Você pode querer tentar Stackless Python ou o greenlet extensão Python, os quais fornecem co-rotinas, com base no qual é possível construir continutations one-shot, mas que ainda é mais fraca do que callcc
de ruby ??(que fornece continuações completo).
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()