Daniel
Daniel

Reputation: 1610

Mutable states in F# object expressions

I would like to have a mutable state in an F# object expression. The first approach is to use ref cells as follows:

type PP =
    abstract member A : int

let foo =
    let a = ref 0
    { new PP with
        member x.A = 
            let ret = !a
            a := !a + 1
            ret 
    }

printfn "%A" foo.A
printfn "%A" foo.A
printfn "%A" foo.A
printfn "%A" foo.A

A different approach would be as follows:

type State(s : int) =
    let mutable intState = s
    member x.state 
        with get () = intState
        and set v = intState <- v 

[<AbstractClass>]         
type PPP(state : State) =
    abstract member A : int
    member x.state 
        with get () = state.state
        and set v = state.state <- v 

let bar n =
    { new PPP(State(n)) with
        member x.A = 
            let ret = x.state
            x.state <- ret + 1
            ret  
    }

let barA1 = bar 0
printfn "%A" barA1.A
printfn "%A" barA1.A
printfn "%A" barA1.A
printfn "%A" barA1.A

Which version would be likely more performing (I need the state updating x.state <- ret + 1 in performance critical sections)? My guess is that the State object is also allocated on the heap so there is no reason why the second version should be faster. However it is slightly more appealing to use.

Thanks for any feedback and suggestions

Upvotes: 2

Views: 586

Answers (2)

Tomas Petricek
Tomas Petricek

Reputation: 243051

As Daniel said, the last approach is essentially equivalent to using built-in ref.

When using ref, you're allocating two objects - the one that you're returning and the reference cell itself. You can reduce this to just a single allocated object by using a concrete implementation (but I don't think this will matter in practice):

type Stateful(initial:int) = 
  let mutable state = initial
  interface PP with
    member x.A =
      let ret = state
      state <- state + 1
      ret

let foo = 
   Statefull(0) :> PP // Creates a single object that keeps the state as mutable field

Aside, you are using read-only property that modifies internal state of the object and returns a new state each time. This is a dangerous pattern that could be quite confusing - properties with getter shouldn't modify the state, so you should probably use a method (unit -> int) instead.

Upvotes: 5

Daniel
Daniel

Reputation: 47904

Your State class is identical to ref. They're both reference types (you can't capture a mutable value type from an object expression). I would prefer a built-in type when possible. ref is the idiomatic way to represent a heap-allocated mutable value.

If ever in doubt about performance, benchmark it.

Upvotes: 3

Related Questions