La lingua Go ha un'istruzione select
che può essere utilizzata per eseguire il polling di più canali ed eseguire una determinata azione a seconda di quale canale non è vuoto per primo.Come implementare l'equivalente dell'istruzione select di Go per i canali Haskell STM?
E.g.
select {
case a := <- chanA:
foo(a)
case b := <- chanB:
baz(b)
case c := <- chanC:
bar(c)
}
Ciò aspettare che sia chanA
, chanB
o chanC
non è vuoto, quindi se per esempio chanB
non è vuota, leggerà da chanB
e memorizzare il risultato in b
, quindi chiamare baz(b)
. Può anche essere aggiunta una clausola default:
, il che significa che l'istruzione select
non attenderà sui canali e invece farà qualunque sia la clausola default
se tutti i canali sono vuoti.
Quale sarebbe il modo migliore per implementare qualcosa come questo per STM TChan
s in Haskell? Potrebbe essere fatto ingenuamente da una catena if else: controllando se ogni chan isEmptyChan
, e se non è vuoto, leggendo da esso e chiamando la funzione appropriata, oppure chiamando retry
se tutti i canali sono vuoti. Mi stavo chiedendo se ci sarebbe stato un modo più elegante/idiomatico per fare questo?
Si noti che l'istruzione select
di Go può includere anche istruzioni di invio nei suoi casi e completerà un'istruzione di invio solo se il canale è vuoto. Sarebbe bello se anche quella funzionalità potesse essere duplicata, anche se non sono sicuro se ci sarebbe un modo elegante per farlo.
Solo un po 'legato, ma qualcosa che ho appena notato e non sono sicuro dove post it: c'è un errore di battitura nella pagina Control.Monad.STM nella descrizione per retry
:
"L'implementazione può bloccare il filo fino a quando uno dei TVars da cui ha letto è stato udpated. "
Si potrebbe voler guardare a 'r ace' da 'Control.Concurrent.Async'. –
Vale la pena notare che go non esegue la prima azione disponibile, ma quella disponibile, selezionata casualmente. In particolare, non affamerà i canali solo perché sono definiti più tardi o sfortunati nel percorso di selezione. – Dustin
Questo è completamente diverso da quello di Go 'select'. I canali in Go sono limitati, diversamente da 'TChan' (rendendoli effettivamente utili) e' select' può essere usato con le operazioni di invio. – rightfold