Ich habe einen Socket-Server, der auf einer Schleife zu akzeptieren Kunden ausgeführt werden muss, so dass ich herausgefunden, dass in funcional Programmierung, eine rekursive Schleife verwendet wird:F # Endlosschleifen 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()
Und dieser Code aufgerufen wird, by doing:
Angesichts der Tatsache, dass die App kontinuierlich ausgeführt wird, sollte ich stattdessen einen iterativen Ansatz verwenden? Erstellt der rec
Ansatz geschachtelte Ausführungsstapel?
Auch ich möchte etwas, nachdem die Schleifenenden tun, wie:
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
Aber dann kann es nicht, weil die awaitConnections
Rückgabetyp kompilieren. Wie könnte ich das tun? Mache ich das richtig?
Danke! Wo finde ich weitere Informationen zu 'return!' vs. 'do!'? – vtortola
Das ist eine geladene Frage, aber ich werde es versuchen. Berechnungsausdrücke wie Async sind syntaktischer Zucker für eine Reihe von Funktionsaufrufen, und das Rückgabeelement ist das Ergebnis der Funktionen. 'do!' definiert einen Ausdruck, der 'unit' zurückgibt, was (in diesem Fall) im Grunde ein neues' Async <'a> '-Objekt erzeugt, das nur zwischen einem rekursiven Aufruf und dem nächsten auftritt,' return! 'vermeidet dies. Zugegebenermaßen bedarf es einiger Überlegungen darüber, wie Async-Objekte hinter den Kulissen funktionieren, um alles möglich zu machen. –
Danke, sehr hilfreich. – vtortola