Should workflows without asynchronous operations be automated in F #?
If I have a parameterless async parameterless workflow in F #, is it necessary and / or idiomatic to make this function, or is it better to leave it as the original value?
For example, if I want to determine whether it getRemoteCounterAfterOneSec
will poll some remote counter source if it should be
let getRemoteCounterAfterOneSec =
async {
do! Async.Sleep 1000
return! ...
}
or
let getRemoteCounterAfterOneSec () =
async {
do! Async.Sleep 1000
return! ...
}
It seems that they should be doing the same thing, only the latter has an unnecessary parameter. However, I saw how this was done in two versions of the code. I've also seen places where behavior ends up differently: if you use MailboxProcessor
and do
let myFunc = mailboxProc.PostAndAsyncReply(fun reply -> GetCount reply)
async {
let! count1 = myFunc
let! count2 = myFunc
}
then the mailbox is processed only once; the second time it just returns the same value computed in the previous call. However, if myFunc
is a function, it calls mailboxProcessor twice as you'd expect.
let myFunc() = mailboxProc.PostAndAsyncReply(fun reply -> GetCount reply)
async {
let! count1 = myFunc()
let! count2 = myFunc()
}
Is this an implementation bug? What's going on here and what is the idiom?
source to share
When it comes to regular async that you define yourself, the addition ()
has no effect (well, it means that the async process that describes the computation is instantiated repeatedly, but it has no practical effect).
I sometimes write this just to make my code clearer or when the async is recursive (because then you get a warning when you have a recursive value). So everything is fine, but this gives you a warning:
let rec loop =
async {
do! Async.Sleep 1000
if 1 > 2 then return 1
else return! loop }
The method is PostAndAsyncReply
written a little differently - and the name tries to reflect that. Common F # asynchronization methods are called AsyncFooBar
. It has PostAndAsyncFooBar
to indicate that it sends first and then waits asynchronously, something like:
let PostAndAsyncWait () =
post(message)
async { let! sth = wait ()
return sth }
So, here it is actually being placed outside of async - this allows you to call the function even if you are (syntactically) outside the block async
. And the name is trying to be very explicit. (But I personally would prefer it to be inside async, i.e. AsyncPostAndWait
).
source to share