Domanda

Qual è la differenza tra un coroutine e una continuazione e un generatore?

È stato utile?

Soluzione

Comincerò con generatori, visto che sono il caso più semplice. Come @zvolkov menzionato, sono funzioni / oggetti che possono essere chiamati ripetutamente senza restituire, ma quando chiamati tornerà (resa) un valore e quindi sospendere la loro esecuzione. Quando sono chiamati ancora una volta, si avvia da dove lo scorso sospese l'esecuzione e fare di nuovo le loro cose.

Un generatore è essenzialmente un (asimmetrica) coroutine tagliato. La differenza tra un coroutine e generatore è che un coroutine può accettare argomenti dopo che è stato inizialmente chiamato, mentre un generatore non può.

E 'un po' difficile a venire con un esempio banale di dove occorre utilizzare coroutine, ma qui è la mia migliore prova. Prendete questa (fatta) codice Python come esempio.

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 esempio di dove sono utilizzati coroutine è lexer e parser. Senza coroutine nella lingua o emulato in qualche modo, lexing e codice di analisi deve essere mescolati insieme anche se sono davvero due preoccupazioni separati. Ma usando un coroutine, è possibile separare il codice lexing e l'analisi.

(sto andando a pennello sopra la differenza tra coroutine simmetrici e asimmetrici Basti dire che sono equivalenti, è possibile convertire da uno all'altro, e coroutine asimmetriche -. Che sono la maggior parte come generators- -sono il più facile da capire. ero delineando come si potrebbe implementare coroutine asimmetrici in Python.)

Continuazioni sono in realtà molto semplici bestie. Tutti sono, sono funzioni che rappresentano un altro punto del programma che, se lo si chiama, causerà esecuzione per passare automaticamente al punto tale funzione rappresenta. Si utilizza versioni molto ristretto di loro ogni giorno senza nemmeno rendersene conto. Eccezioni, per esempio, possono essere considerati come una sorta di continuazione dentro-fuori. Vi darò un esempio pseudocodice Python basata su una continuazione.

Say Python ha una funzione chiamata callcc(), e questa funzione ha due argomenti, il primo è una funzione, e la seconda è un elenco di argomenti da chiamare con. L'unica limitazione che la funzione sarebbe che l'ultimo argomento che ci vuole sarà una funzione (che sarà il nostro attuale continuazione).

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

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

cosa accadrebbe è che callcc() avrebbe a sua volta chiamata foo() con la continuazione corrente (cc), cioè, un riferimento al punto del programma in cui callcc() stato chiamato. Quando foo() chiama la continuazione corrente, è essenzialmente lo stesso di raccontare callcc() di tornare con il valore che si sta chiamando la continuazione corrente con, e quando lo fa che, rotola di nuovo la pila al punto in cui la continuazione corrente è stato creato, cioè quando hai chiamato callcc().

Il risultato di tutto questo sarebbe che la nostra variante Python ipotetico stampare '42'.

Mi auguro che aiuta, e sono sicuro che la mia spiegazione può essere migliorata su un bel po '!

Altri suggerimenti

coroutine è una delle varie procedure che si alternano facendo il loro lavoro e poi una pausa per dare il controllo agli altri co-routine del gruppo.

Continuazione è un "puntatore ad una funzione" si passa a qualche procedura, da eseguire ( "continua con") quando tale procedura viene eseguita.

Generator (NET) è un costrutto del linguaggio che può sputare un valore, "pausa" esecuzione del metodo e quindi procedere dallo stesso punto quando viene richiesta la valore successivo.

Nella versione più recente di Python, è possibile inviare i valori di generatori con generator.send(), che rende generatori Python coroutine efficace.

La differenza principale tra pitone Generator, e altro generatore, dicono greenlet, è che in Python, il vostro yield value può restituire solo al chiamante. Mentre in greenlet, target.switch(value) si può prendere ad una specifica coroutine target e produrre un valore in cui il target avrebbe continuato a funzionare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top