Corutina vs Continuación vs Generador


¿Cuál es la diferencia entre una corrutina y una continuación y un generador ?

Author: Benson, 2009-04-04

3 answers

Comenzaré con generadores, ya que son el caso más simple. Como @ zvolkov mencionó, son funciones / objetos que se pueden llamar repetidamente sin devolver, pero cuando se llaman devolverán (producirán) un valor y luego suspenderán su ejecución. Cuando los llamen de nuevo, comenzarán desde donde suspendieron la ejecución por última vez y volverán a hacer lo suyo.

Un generador es esencialmente una coroutina de corte (asimétrica). La diferencia entre una corrutina y un generador es que un coroutine puede aceptar argumentos después de que se ha llamado inicialmente, mientras que un generador no puede.

Es un poco difícil para algunos con un ejemplo trivial de dónde usarías corrutinas, pero aquí está mi mejor intento. Tome este código Python (inventado) como ejemplo.

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

Un ejemplo de donde se usan las corrutinas son los lexers y los analizadores. Sin coroutinas en el lenguaje o emulado de alguna manera, el código de lexing y parsing debe mezclarse aunque realmente sean dos separados preocupación. Pero usando una corrutina, puedes separar el código lexing y el código de análisis.

(Voy a repasar la diferencia entre las corrutinas simétricas y asimétricas. Baste decir que son equivalentes, se puede convertir de uno a otro, y asimétrica corrutinas, - que son la mayoría como los generadores que son las más fáciles de entender. Me fue explicando cómo uno podría implementar asimétrica corrutinas en Python.)

Las continuaciones son en realidad bestias bastante simples. Todo son funciones que representan otro punto en el programa que, si lo llamas, hará que la ejecución cambie automáticamente al punto que representa la función. Utilizas versiones muy restringidas de ellos todos los días sin siquiera darte cuenta. Las excepciones, por ejemplo, pueden considerarse como una especie de continuación de adentro hacia afuera. Te daré un ejemplo de pseudocódigo basado en Python de una continuación.

Digamos que Python tenía una función llamada callcc(), y esta función tomó dos argumentos, el primero siendo una función, y el segundo siendo una lista de argumentos para llamarlo con. La única restricción en esa función sería que el último argumento que tome será una función (que será nuestra continuación actual).

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

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

Lo que sucedería es que callcc() a su vez llamaría foo() con la continuación actual (cc), es decir, una referencia al punto en el programa en el que se llamó callcc(). Cuando foo() llama a la continuación actual, es esencialmente lo mismo que decirle a callcc() que devuelve con el valor con el que estás llamando a la continuación actual, y cuando lo hace, devuelve la pila al lugar donde se creó la continuación actual, es decir, cuando llamaste callcc().

El resultado de todo esto sería que nuestra variante hipotética de Python imprimiría '42'.

Espero que eso ayude, y estoy seguro de que mi explicación se puede mejorar un poco!

 109
Author: Keith Gaughan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-16 19:53:37

La corrutina es uno de varios procedimientos que se turnan para hacer su trabajo y luego hacen una pausa para dar control a las otras corrutinas del grupo.

Continuation es un "puntero a una función" que pasa a algún procedimiento, para ser ejecutado ("continued with") cuando ese procedimiento se realiza.

Generator (en.NET) es una construcción de lenguaje que puede escupir un valor, "pausar" la ejecución del método y luego proceder desde el mismo punto cuando se le pide el siguiente valor.

 29
Author: zvolkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-07 22:35:12

En la versión más reciente de Python, puede enviar valores a los generadores con generator.send(), lo que hace que los generadores de python sean efectivamente corrutinas.

La principal diferencia entre el Generador python y otro generador, digamos greenlet, es que en python, su yield value solo puede regresar al llamador. Mientras que en greenlet, target.switch(value) puede llevarlo a una corrutina de destino específica y obtener un valor donde target continuaría ejecutándose.

 8
Author: Yichuan Wang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-31 02:51:31