Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# async - difference between two structure

Is there a difference between writing something like this:

MailboxProcessor.Start(fun inbox -> async {
    let rec loop bugs =
        let! msg = inbox.Receive()
        let res = //something
        loop res
    loop []})

And writing it like this:

MailboxProcessor.Start(fun inbox ->
    let rec loop bugs = async {
        let! msg = inbox.Receive()
        let res = //something
        do! loop res }
    loop [])

Thanks!

like image 857
David Grenier Avatar asked Aug 01 '11 22:08

David Grenier


1 Answers

The first example is not valid F# code, because let! can only be used immediately inside computation expression. In your example, you're using it in an ordinary function - its body is not a computation expression, so let! is not allowed in that position.

To make it valid, you'd need to wrap the body of the loop function inside async:

MailboxProcessor.Start(fun inbox -> async {
    let rec loop bugs = async {
        let! msg = inbox.Receive()
        let res = //something
        return! loop res }
    return! loop []})

You can keep the outer async { .. } block in the snippet as well - then you just need to use return! to call your loop function instead of just returning it (but other than that there is no significant difference now).

Note that I used return! instead of do! - this actually makes a difference, because return! represents a tail-call, which means that the rest of the current body can be discarded. If you use do! then the async allocates something like a stack frame in the heap, so using do! in a recursive looping function leaks memory.

like image 156
Tomas Petricek Avatar answered Sep 28 '22 08:09

Tomas Petricek