Pergunta

O que é a diferença entre uma co-rotina e uma continuação e um gerador?

Foi útil?

Solução

Vou começar com geradores, vendo como eles são o caso mais simples. Como @zvolkov mencionado, eles são funções / objetos que podem ser chamados várias vezes sem retornar, mas quando chamado irá retornar (rendimento) um valor e, em seguida, suspender a sua execução. Quando eles são chamados de novo, eles vão começar a partir execução onde eles última suspensa e fazer as suas coisas novamente.

Um gerador é essencialmente um corte baixo (assimétrica) co-rotina. A diferença entre uma co-rotina e gerador é que uma co-rotina pode aceitar argumentos depois de ter sido inicialmente chamado, enquanto um gerador não pode.

É um pouco difícil para chegar a um exemplo trivial de onde você usaria coroutines, mas aqui é a minha melhor tentativa. Tome este (composta) de código Python como um exemplo.

def my_coroutine_body(*args):
    while True:
        # Do some funky stuff
        *args = yield value_im_returning
        # Do some more funky stuff

my_coro = make_coroutine(my_coroutine_body)

x = 0
while True:
   # The coroutine does some funky stuff to x, and returns a new value.
   x = my_coro(x)
   print x

Um exemplo de onde são utilizados coroutines é lexers e analisadores. Sem coroutines na língua ou emulado de alguma forma, léxico e parsing necessidades de código para ser misturados entre si, embora eles são realmente duas preocupações distintas. Mas usando uma co-rotina, você pode separar o código lexing e análise.

(Eu vou escovar sobre a diferença entre coroutines simétricas e assimétricas Basta dizer que eles são equivalentes, você pode converter de um para o outro, e assimétricas coroutines -. Que são mais como generators- -são mais fácil a compreensão. Eu estava descrevendo como se pode implementar co-rotinas assimétricas em Python.)

Continuations são realmente animais muito simples. Tudo o que eles são, são funções que representam outro ponto do programa que, se você chamá-lo, fará com que a execução para mudar automaticamente para o ponto de que a função representa. Você usa versões muito restrito de todos os dias, mesmo sem perceber. Exceções, por exemplo, pode ser pensado como uma espécie de continuação de dentro para fora. Vou te dar um exemplo pseudocódigo baseado em Python de uma continuação.

Say Python teve uma função chamada callcc(), e esta função levou dois argumentos, o primeiro sendo uma função, eo segundo é uma lista de argumentos para chamá-lo com. A única restrição a essa função seria a de que o último argumento que leva será uma função (que será a nossa continuação atual).

def foo(x, y, cc):
   cc(max(x, y))

biggest = callcc(foo, [23, 42])
print biggest

O que aconteceria é que callcc(), por sua vez foo() chamada com a continuação atual (cc), isto é, uma referência para o ponto no programa em que callcc() foi chamado. Quando foo() chama a continuação atual, que é essencialmente o mesmo que dizer callcc() para retornar com o valor que você está chamando a continuação atual com, e quando ele faz isso, ele reverte a pilha para onde a continuação atual foi criado, ou seja, quando você chamou callcc().

O resultado de tudo isso seria que a nossa hipotética variante Python iria imprimir '42'.

Espero que ajude, e eu tenho certeza que a minha explicação pode ser melhorado um pouco!

Outras dicas

co-rotina é um dos vários procedimentos que se revezam fazendo seu trabalho e, em seguida, fazer uma pausa para dar o controle aos outros co-rotinas no grupo.

A continuação é um "ponteiro para uma função" você passa a algum procedimento, a ser executada ( "continuou com") quando esse procedimento é feito.

Generator (na NET) é um construtor de linguagem que pode cuspir um valor, "pausa" de execução do método e, em seguida, proceder a partir do mesmo ponto quando perguntado para o próximo valor.

Na versão mais recente do Python, você pode enviar valores para Geradores com generator.send(), o que torna Geradores python efetivamente co-rotinas.

A principal diferença entre python Generator, e outro gerador, digamos greenlet, é que, em python, seu yield value só pode voltar para o chamador. Enquanto em greenlet, target.switch(value) pode levá-lo para uma co-rotina alvo específico e produzir um valor onde a target iria continuar a funcionar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top