When you think you know, you don't know, is what went through my head earlier today. While going over someone's code I noticed something similar to:
task {
let mutable pleaseContinue = true
let mutable state = MyState.Running
while pleaseContine do
match x with
| Ok ->
// do something
do! runSomeTasks()
state <- MyState.Running
pleaseContinue <- true
| Error err ->
do! Log.Fatal err "Something bad"
state <- MyState.Crashed
pleaseContinue <- false
| ... // originally many other states
return
}
Basically, whenever I see mutable
in someone else's code I tend to want to get rid of it. But short of that, I found myself wondering whether the mutable variables inside task
and the like are properly part of the closure and are safe to read/update/write, as long as they aren't defined outside the task
CE builder.
Is this a correct and safe assumption?
This is in F# 6.0, and using Microsoft.FSharp.Control.TaskBuilder
and friends.
This looks fine to me.
See https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions.
The builder implements the body of the while loop as a recursive function. It can modify
state
andpleaseContinue
since the variables are in scope.I'm just not clear where the
x
that you refer to is declared or mutated - presumably as part of the omitted code before thereturn
statement. In any case, if it is in scope, it should be fine.