Изменяемые состояния в выражениях объекта F # - PullRequest
2 голосов
/ 17 ноября 2011

Я хотел бы иметь изменяемое состояние в выражении объекта 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 также размещается в куче, поэтому нет причин, почему вторая версия должна быть быстрее.Однако это немного более привлекательно для использования. </p>

Спасибо за любые отзывы и предложения

Ответы [ 2 ]

5 голосов
/ 17 ноября 2011

Как сказал Даниэль, последний подход по сути эквивалентен использованию встроенного 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

Кроме того, вы используете свойство только для чтения, которое изменяет внутреннийсостояние объекта и каждый раз возвращает новое состояние.Это опасный шаблон, который может привести к путанице - свойства с помощью getter не должны изменять состояние, поэтому вам, вероятно, следует использовать метод (unit -> int).

3 голосов
/ 17 ноября 2011

Ваш State класс идентичен ref.Оба они являются ссылочными типами (вы не можете захватить изменяемый тип значения из выражения объекта).Я бы предпочел встроенный тип, когда это возможно.ref - это идиоматический способ представления изменяемого значения, выделенного в куче.

Если есть сомнения в производительности, сравните его.

...