2

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

別のアプローチは次のようになります。

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

どちらのバージョンがよりパフォーマンスが高い可能性がありますか (パフォーマンスの重要なセクションで x.state <- ret + 1 を更新する状態が必要です)? 私の推測では、State オブジェクトもヒープに割り当てられているため、2 番目のバージョンが高速になる理由はありません。ただし、使用するのは少し魅力的です。

フィードバックや提案をありがとう

4

2 に答える 2

5

ダニエルが言ったように、最後のアプローチは組み込みの使用と本質的に同等refです。

を使用する場合ref、返されるオブジェクトと参照セル自体の 2 つのオブジェクトを割り当てます。具体的な実装を使用して、これを単一の割り当てられたオブジェクトに減らすことができます (ただし、これは実際には問題にならないと思います)。

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

さておき、オブジェクトの内部状態を変更し、毎回新しい状態を返す読み取り専用プロパティを使用しています。これは非常に紛らわしい危険なパターンです。getter を使用したプロパティは状態を変更してはならないため、unit -> int代わりにメソッド ( ) を使用する必要があります。

于 2011-11-17T17:05:57.197 に答える
3

あなたのStateクラスは と同じですref。どちらも参照型です (オブジェクト式から可変値型をキャプチャすることはできません)。できればビルトインタイプがいいと思います。refヒープに割り当てられた可変値を表す慣用的な方法です。

パフォーマンスに疑問がある場合は、ベンチマークしてください。

于 2011-11-17T16:32:20.857 に答える