Ho un server socket che deve essere eseguito su un loop di accettare i clienti, così ho scoperto che nella programmazione funcional, un ciclo ricorsivo si usa:F # ciclo continuo in F #
let awaitConnections (wsl:WebSocketListener) =
let rec loop()=
async {
let! ws = Async.AwaitTask (wsl.AcceptWebSocketAsync(cancellation.Token))
printfn "Connection from %s" (ws.RemoteEndpoint.Address.ToString())
Async.Start <| awaitMessages ws
do! loop()}
loop()
E questo codice viene richiamato facendo:
Async.Start <| awaitConnections listener
Considerando che l'applicazione viene eseguita continuamente, dovrei invece utilizzare un approccio iterativo? L'approccio rec
crea stack di esecuzione nidificati?
Inoltre, mi piacerebbe fare qualcosa dopo la fine del ciclo, come:
let awaitConnections (wsl:WebSocketListener) =
let rec loop()=
async {
let! ws = Async.AwaitTask (wsl.AcceptWebSocketAsync(cancellation.Token))
printfn "Connection from %s" (ws.RemoteEndpoint.Address.ToString())
Async.Start <| awaitMessages ws
do! loop()}
loop()
printf "The loop ended" // <-- this line
ma poi non riesco a compilare perché il tipo awaitConnections
ritorno. Come potrei farlo? Lo sto facendo bene?
Grazie! dove posso trovare maggiori informazioni su 'return!' vs. 'do!'? – vtortola
Questa è una domanda caricata, ma farò un tentativo. Le espressioni di calcolo come 'async' sono zucchero sintattico per una serie di chiamate di funzione, e l'elemento di ritorno è il risultato delle funzioni. 'do!' definisce un'espressione che restituisce 'unit', che (in questo caso) crea fondamentalmente un nuovo oggetto' Async <'a>' che non fa altro che passare tra una chiamata ricorsiva e il successivo, 'return!' lo evita. Certo, questo prende in considerazione il modo in cui gli oggetti 'Async' lavorano dietro le quinte per far accadere tutto. –
Grazie, molto utile. – vtortola