F#对象表达式中的可变状态

Dan*_*iel 2 f# mutable ref

我想在F#对象表达式中有一个可变状态.第一种方法是使用ref单元格如下:

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
Run Code Online (Sandbox Code Playgroud)

一种不同的方法如下:

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
Run Code Online (Sandbox Code Playgroud)

哪个版本的性能可能更高(我需要在性能关键部分更新x.state < - ret + 1的状态)?我的猜测是State对象也在堆上分配,所以没有理由为什么第二个版本应该更快.然而,它使用起来更有吸引力.

感谢您的任何反馈和建议

Tom*_*cek 5

正如丹尼尔所说,最后一种方法基本上等同于使用内置方法ref.

使用时ref,您将分配两个对象 - 您要返回的对象和参考单元本身.您可以通过使用具体实现将此减少为仅一个已分配的对象(但我不认为这在实践中很重要):

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
Run Code Online (Sandbox Code Playgroud)

除此之外,您正在使用只读属性来修改对象的内部状态,并且每次都返回一个新状态.这是一个非常混乱的危险模式 - 带有getter的属性不应该修改状态,所以你应该使用方法(unit -> int)代替.