I have a multi-state F# MailboxProcessor example here, just wondering why it compiles but the behavior is unexpected - can F# agents only have one inbox.Receive() statement in the passed in lambda function? I am trying to follow the general example pattern provided in "Expert F# 3.0" page 284, where the use of multiple async {} bodies allows multiple states, but it isn't specific as to whether the inbox.Receive() can be used in each async?
open System
let mb1<'T> = MailboxProcessor<string>.Start(fun inbox ->
let rec loop1 (n:int) = async {
printfn "loop1 entry "
let! msg = inbox.Receive()
do! Async.Sleep(1000)
printfn "loop1 calling loop2" //msg received %A" msg
return! loop2 (n+1) }
and loop2 (x:int) = async {
printfn "loop2 entry"
let! msg2 = inbox.Receive()
printfn "loop2 msg received %A" msg2
printfn "loop2 calling loop1"
return! loop1 (x+1) }
loop2 0
)
mb1.Post("data message 1")
mb1.Post("data message 2")
yields
loop2 entry
loop2 msg received "data message 1"
loop2 calling loop1
loop1 entry
val it : unit = ()
>
loop2 entry
loop2 msg received "data message 2"
loop2 calling loop1
loop1 entry
val it : unit = ()
>
so the let! msg = inbox.Receive() in loop 1 is skipped? I would have thought that loop2 is completed by the return! loop1 and that the let! assignment of the inbox.Receive() is specific to the async block in which it used.