2011-06-08 12 views

risposta

6

Sì, reset s può essere annidato e, sì, può essere utile. Ad esempio, di recente ho prototipato un'API per lo scalagwt project che consentirebbe agli sviluppatori GWT di scrivere RPC asincroni (chiamate di procedure remote) in uno stile diretto (in opposizione allo stile di passaggio di callback utilizzato in GWT per Java). Ad esempio:

field1 = "starting up..."     // 1 
field2 = "starting up..."     // 2 
async {          // (reset) 
    val x = service.someAsyncMethod()  // 3 (shift) 
    field1 = x        // 5 
    async {         // (reset) 
     val y = service.anotherAsyncMethod() // 6 (shift) 
     field2 = y       // 8 
    } 
    field2 = "waiting..."     // 7 
} 
field1 = "waiting..."      // 4 

I commenti indicano l'ordine di esecuzione. Qui, il metodo async esegue un reset e ogni chiamata di servizio esegue un shift (è possibile vedere l'implementazione su my github fork, in particolare Async.scala).

Nota come il nidificato async modifica il flusso di controllo. Senza di esso, la riga field2 = "waiting" non verrà eseguita fino a dopo il completamento con esito positivo del secondo RPC.

Quando un RPC è fatto, l'attuazione cattura la continuazione fino al più interno async confine e sospende per un esecuzione dopo il completamento della RPC. Pertanto, il blocco nidificato async consente al controllo di passare immediatamente alla riga successiva non appena viene creato il secondo RPC. Senza quel blocco nidificato, d'altra parte, la continuazione si estenderebbe fino alla fine del blocco esterno async, nel qual caso tutto il codice all'interno dello async esterno verrebbe bloccato su ogni RPC.

1

reset forma un'astrazione in modo che il codice esterno non sia influenzato dal fatto che il codice interno è implementato con la magia di continuazione. Quindi, se stai scrivendo il codice con reset e shift, può chiamare un altro codice che può essere implementato o meno con reset e shift. In questo senso possono essere annidati.

Problemi correlati