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

Foi útil?

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()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top