'Is it safe to use mutable let bindings inside task CEs or async CEs?

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.



Solution 1:[1]

This looks fine to me.

See https://docs.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 and pleaseContinue 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 the return statement. In any case, if it is in scope, it should be fine.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Roland Andrag